protected bool IsExpired(SimpleWebToken accessToken)
        {
            if (accessToken.ValidTo > DateTime.UtcNow)
            {
                return(false);
            }

            return(true);
        }
        private static IDictionary <string, string> ToDictionary(SimpleWebToken token)
        {
            var dictionary = new Dictionary <string, string>
            {
                { "Issuer", token.Issuer },
                { "Audience", token.Audience }
            };

            return(dictionary);
        }
        public override SecurityToken GetTokenFromString(string token)
        {
            // TODO: validate
            var items  = HttpUtility.ParseQueryString(token);
            var issuer = items[IssuerLabel];

            items.Remove(IssuerLabel);
            var audience = items[AudienceLabel];

            items.Remove(AudienceLabel);
            var expiresOn = items[ExpiresOnLabel];

            items.Remove(ExpiresOnLabel);
            var id = items[IdLabel];

            items.Remove(IdLabel);
            var algorithm = items[SignatureAlgorithmLabel];

            items.Remove(SignatureAlgorithmLabel);

            // Treat signature differently to avoid loosing characters like '+' in the decoding
            var signature = ExtractSignature(HttpUtility.UrlDecode(token));

            items.Remove(SignatureLabel);

            byte[]   signatureBytes = Convert.FromBase64String(signature);
            DateTime validTo        = this.GetDateTimeFromExpiresOn((ulong)Convert.ToInt64(expiresOn));

            var swt = new SimpleWebToken(issuer)
            {
                Audience      = audience,
                Signature     = signatureBytes,
                TokenValidity = validTo - DateTime.UtcNow
            };

            if (id != null)
            {
                swt.SetId(id);
            }

            if (string.IsNullOrEmpty(algorithm))
            {
                swt.SignatureAlgorithm = algorithm;
            }

            foreach (string key in items.AllKeys)
            {
                swt.AddClaim(key, items[key]);
            }

            swt.RawToken = token;

            return(swt);
        }
        protected bool IsValidSignature(SimpleWebToken token, byte[] signingKey)
        {
            var unsignedToken = this.GetUnsignedToken(token.RawToken);

            if (string.IsNullOrEmpty(unsignedToken))
            {
                return(false);
            }

            var localSignature    = GenerateSignature(unsignedToken, signingKey);
            var incomingSignature = HttpUtility.UrlEncode(Convert.ToBase64String(token.Signature));

            return(localSignature.Equals(incomingSignature, StringComparison.Ordinal));
        }
        protected bool IsAudienceTrusted(SimpleWebToken accessToken)
        {
            if (this.AudienceRestriction.AudienceMode == AudienceUriMode.Never)
            {
                return(true);
            }

            if (!string.IsNullOrEmpty(accessToken.Audience))
            {
                return(this.AudienceRestriction.AllowedAudienceUris.Contains(new Uri(accessToken.Audience)));
            }

            return(false);
        }
        private bool IsIssuerTrusted(SimpleWebToken accessToken, out string issuerName)
        {
            issuerName = null;
            if (!string.IsNullOrEmpty(accessToken.Issuer))
            {
                if (this.IssuerNameRegistry != null)
                {
                    issuerName = this.IssuerNameRegistry.GetIssuerName(accessToken);
                    if (!string.IsNullOrEmpty(issuerName))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
        public override string GetTokenAsString(SecurityToken token)
        {
            SimpleWebToken swt = token as SimpleWebToken;

            if (swt == null)
            {
                throw new Exception("Incorrect token type. Expected SimpleWebToken");
            }

            if (this.SecurityTokenResolver == null)
            {
                throw new InvalidOperationException("SecurityTokenResolver is not configured");
            }

            var swtSigned = SerializeToken(swt, this.SecurityTokenResolver);

            return(swtSigned);
        }
        protected static string SerializeToken(SimpleWebToken swt, SecurityTokenResolver tokenResolver)
        {
            StringBuilder builder = new StringBuilder(64);

            builder.Append("Id=");
            builder.Append(swt.Id);
            builder.Append('&');

            builder.Append(IssuerLabel);
            builder.Append('=');
            builder.Append(swt.Issuer);

            if (swt.Parameters.Count > 0)
            {
                builder.Append('&');
                foreach (string key in swt.Parameters.AllKeys)
                {
                    builder.Append(key);
                    builder.Append('=');
                    builder.Append(swt.Parameters[key]);
                    builder.Append('&');
                }
            }
            else
            {
                builder.Append('&');
            }

            builder.Append(ExpiresOnLabel);
            builder.Append('=');
            builder.Append(GetExpiresOn(swt.TokenValidity));

            if (!string.IsNullOrEmpty(swt.Audience))
            {
                builder.Append('&');
                builder.Append(AudienceLabel);
                builder.Append('=');
                builder.Append(swt.Audience);
            }

            builder.Append('&');
            builder.Append(SignatureAlgorithmLabel);
            builder.Append('=');
            builder.Append(SignatureAlgorithm);

            var keyIdentifierClause = new DictionaryBasedKeyIdentifierClause(ToDictionary(swt));
            InMemorySymmetricSecurityKey securityKey;

            try
            {
                securityKey = (InMemorySymmetricSecurityKey)tokenResolver.ResolveSecurityKey(keyIdentifierClause);
            }
            catch (InvalidOperationException)
            {
                throw new SecurityTokenValidationException(string.Format(CultureInfo.InvariantCulture, "Simmetryc key was not found for the key identifier clause: Keys='{0}', Values='{1}'", string.Join(",", keyIdentifierClause.Dictionary.Keys.ToArray()), string.Join(",", keyIdentifierClause.Dictionary.Values.ToArray())));
            }

            string signature = GenerateSignature(builder.ToString(), securityKey.GetSymmetricKey());

            builder.Append("&" + SignatureLabel + "=");
            builder.Append(signature);

            return(builder.ToString());
        }
        public override ClaimsIdentityCollection ValidateToken(SecurityToken token)
        {
            if (token == null)
            {
                throw new ArgumentNullException("token is null");
            }

            if (this.SecurityTokenResolver == null)
            {
                throw new InvalidOperationException("SecurityTokenResolver is not configured");
            }

            if (this.IssuerNameRegistry == null)
            {
                throw new InvalidOperationException("IssuerNameRegistry is not configured");
            }

            if (this.AudienceRestriction == null)
            {
                throw new InvalidOperationException("AudienceRestriction is not configured");
            }

            SimpleWebToken accessToken = token as SimpleWebToken;

            if (accessToken == null)
            {
                throw new ArgumentNullException("This handler expects a SimpleWebToken");
            }

            var keyIdentifierClause = new DictionaryBasedKeyIdentifierClause(ToDictionary(accessToken));
            InMemorySymmetricSecurityKey securityKey;

            try
            {
                securityKey = (InMemorySymmetricSecurityKey)this.SecurityTokenResolver.ResolveSecurityKey(keyIdentifierClause);
            }
            catch (InvalidOperationException)
            {
                throw new SecurityTokenValidationException(string.Format(CultureInfo.InvariantCulture, "Simmetryc key was not found for the key identifier clause: Keys='{0}', Values='{1}'", string.Join(",", keyIdentifierClause.Dictionary.Keys.ToArray()), string.Join(",", keyIdentifierClause.Dictionary.Values.ToArray())));
            }

            if (!this.IsValidSignature(accessToken, securityKey.GetSymmetricKey()))
            {
                throw new SecurityTokenValidationException("Signature is invalid");
            }

            if (this.IsExpired(accessToken))
            {
                throw new SecurityTokenException(string.Format("Token has been expired for {0} seconds already", (DateTime.UtcNow - accessToken.ValidTo).TotalSeconds));
            }

            string issuerName;

            if (!this.IsIssuerTrusted(accessToken, out issuerName))
            {
                throw new SecurityTokenException(string.Format("The Issuer {0} is not trusted", accessToken.Issuer));
            }

            if (!this.IsAudienceTrusted(accessToken))
            {
                throw new SecurityTokenException(string.Format("The audience {0} of the token is not trusted", accessToken.Audience));
            }

            var identity = this.CreateClaimsIdentity(accessToken.Parameters, issuerName);

            return(new ClaimsIdentityCollection(new IClaimsIdentity[] { identity }));
        }