/// <summary>
        /// Verifies the signature of the incoming token.
        /// </summary>
        /// <param name="key">The key used for signing.</param>
        /// <returns>true if the signatures match, false otherwise.</returns>
        public bool SignVerify(SimpleWebToken token, byte[] key)
        {
            if (token == null)
            {
                throw new ArgumentNullException("token");
            }

            if (key == null)
            {
                throw new ArgumentNullException("key");
            }

            var unsignedToken = CreateUnsignedToken(token);

            string verifySignature;

            using (HMACSHA256 signatureAlgorithm = new HMACSHA256(key))
            {
                verifySignature = Convert.ToBase64String(signatureAlgorithm.ComputeHash(Encoding.ASCII.GetBytes(unsignedToken)));
            }

            if (string.CompareOrdinal(verifySignature, token.Signature) == 0)
            {
                return(true);
            }

            return(false);
        }
Example #2
0
        public override ReadOnlyCollection <ClaimsIdentity> ValidateToken(SecurityToken token)
        {
            SimpleWebToken swt = token as SimpleWebToken;

            if (swt == null)
            {
                throw new SecurityTokenValidationException("The received token is of incorrect token type.Expected SimpleWebToken");
            }

            // check issuer name registry for allowed issuers
            string issuerName = swt.Issuer;

            // check expiration
            if (DateTime.Compare(swt.ValidTo, DateTime.UtcNow) <= 0)
            {
                throw new SecurityTokenExpiredException("The incoming token has expired. Get a new access token from the Authorization Server.");
            }

            // check audience
            if (base.Configuration.AudienceRestriction.AudienceMode != AudienceUriMode.Never)
            {
                var allowedAudiences = base.Configuration.AudienceRestriction.AllowedAudienceUris;

                if (!allowedAudiences.Any(uri => uri == swt.AudienceUri))
                {
                    throw new AudienceUriValidationFailedException();
                }
            }

            // retrieve signing key
            var clause      = new NamedKeySecurityKeyIdentifierClause(swt.Issuer, swt.Issuer);
            var securityKey = Configuration.IssuerTokenResolver.ResolveSecurityKey(clause) as InMemorySymmetricSecurityKey;

            if (securityKey == null)
            {
                throw new SecurityTokenValidationException("No signing key found");
            }

            // check signature
            if (!swt.VerifySignature(securityKey.GetSymmetricKey()))
            {
                throw new SecurityTokenValidationException("Signature verification of the incoming token failed.");
            }

            var id = new ClaimsIdentity("SWT");

            foreach (var claim in swt.Claims)
            {
                var value = claim.Value;
                value.Split(',').ToList().ForEach(v => id.AddClaim(new Claim(claim.Type, HttpUtility.UrlDecode(v), ClaimValueTypes.String, issuerName)));
            }

            return(new ReadOnlyCollection <ClaimsIdentity>(new ClaimsIdentity[] { id }));
        }
        private static string CreateUnsignedToken(SimpleWebToken swt)
        {
            var sb = new StringBuilder();

            CreateClaims(swt, sb);

            sb.AppendFormat("Issuer={0}&", HttpUtility.UrlEncode(swt.Issuer));
            sb.AppendFormat("Audience={0}&", HttpUtility.UrlEncode(swt.AudienceUri.AbsoluteUri));
            sb.AppendFormat("ExpiresOn={0:0}", swt.ValidTo.ToEpochTime());

            return(sb.ToString());
        }
        private static void CreateClaims(SimpleWebToken swt, StringBuilder sb)
        {
            var claims = new Dictionary <string, string>();

            foreach (var claim in swt.Claims)
            {
                claims.Add(claim.Type, claim.Value);
            }

            foreach (var kv in claims)
            {
                sb.AppendFormat("{0}={1}&", HttpUtility.UrlEncode(kv.Key), HttpUtility.UrlEncode(kv.Value));
            }
        }
        public override SecurityToken CreateToken(SecurityTokenDescriptor tokenDescriptor)
        {
            var claims   = tokenDescriptor.Subject.Claims;
            var issuer   = tokenDescriptor.TokenIssuerName;
            var audience = tokenDescriptor.AppliesToAddress;
            var key      = (InMemorySymmetricSecurityKey)tokenDescriptor.SigningCredentials.SigningKey;

            var token = new SimpleWebToken(
                new Uri(audience),
                issuer,
                tokenDescriptor.Lifetime.Expires.Value,
                claims.ToList(),
                key);

            return(token);
        }
        private static string CreateUnsignedToken(SimpleWebToken swt)
        {
            var sb     = new StringBuilder();
            var claims = new Dictionary <string, string>();

            foreach (var claim in swt.Claims)
            {
                claims.Add(claim.Type, claim.Value);
            }

            foreach (var kv in claims)
            {
                sb.AppendFormat("{0}={1}&", HttpUtility.UrlEncode(kv.Key), HttpUtility.UrlEncode(kv.Value));
            }

            sb.AppendFormat("Issuer={0}&", HttpUtility.UrlEncode(swt.Issuer));
            sb.AppendFormat("Audience={0}&", HttpUtility.UrlEncode(swt.AudienceUri.AbsoluteUri));
            sb.AppendFormat("ExpiresOn={0:0}", swt.ValidTo.ToEpochTime());

            return(sb.ToString());
        }
        internal static void CreateClaims(SimpleWebToken swt, StringBuilder sb)
        {
            var claims = new Dictionary <string, List <string> >();

            foreach (var claim in swt.Claims)
            {
                if (claims.ContainsKey(claim.ClaimType))
                {
                    claims[claim.ClaimType].Add(claim.Value);
                }
                else
                {
                    claims.Add(claim.ClaimType, new List <string>());
                    claims[claim.ClaimType].Add(claim.Value);
                }
            }

            foreach (var kv in claims)
            {
                var    values = kv.Value;
                string s      = null;

                foreach (var val in values)
                {
                    if (string.IsNullOrEmpty(s))
                    {
                        s = HttpUtility.UrlEncode(val);
                        continue;
                    }

                    s += string.Format(",{0}", HttpUtility.UrlEncode(val));
                }

                sb.AppendFormat("{0}={1}&", HttpUtility.UrlEncode(kv.Key), HttpUtility.UrlEncode(s));
            }
        }
        /// <summary>
        /// Verifies the signature of the incoming token.
        /// </summary>
        /// <param name="key">The key used for signing.</param>
        /// <returns>true if the signatures match, false otherwise.</returns>
        public bool SignVerify(SimpleWebToken token, byte[] key)
        {
            if (token == null)
            {
                throw new ArgumentNullException("token");
            }

            if (key == null)
            {
                throw new ArgumentNullException("key");
            }

            var unsignedToken = CreateUnsignedToken(token);

            string verifySignature;
            using (HMACSHA256 signatureAlgorithm = new HMACSHA256(key))
            {
                verifySignature = Convert.ToBase64String(signatureAlgorithm.ComputeHash(Encoding.ASCII.GetBytes(unsignedToken)));
            }

            if (string.CompareOrdinal(verifySignature, token.Signature) == 0)
            {
                return true;
            }

            return false;
        }
        private static void CreateClaims(SimpleWebToken swt, StringBuilder sb)
        {
            var claims = new Dictionary<string, string>();

            foreach (var claim in swt.Claims)
            {
                claims.Add(claim.ClaimType, claim.Value);
            }

            foreach (var kv in claims)
            {
                sb.AppendFormat("{0}={1}&", HttpUtility.UrlEncode(kv.Key), HttpUtility.UrlEncode(kv.Value));
            }
        }
        public override SecurityToken CreateToken(SecurityTokenDescriptor tokenDescriptor)
        {
            var claims = tokenDescriptor.Subject.Claims;
            var issuer = tokenDescriptor.TokenIssuerName;
            var audience = tokenDescriptor.AppliesToAddress;
            var key = (InMemorySymmetricSecurityKey)tokenDescriptor.SigningCredentials.SigningKey;

            var token = new SimpleWebToken(
                new Uri(audience), 
                issuer, 
                tokenDescriptor.Lifetime.Expires.Value, 
                claims.ToList(), 
                key);

            return token;
        }
        private static string CreateUnsignedToken(SimpleWebToken swt)
        {
            var sb = new StringBuilder();
            var claims = new Dictionary<string, string>();

            foreach (var claim in swt.Claims)
            {
                claims.Add(claim.ClaimType, claim.Value);
            }

            foreach (var kv in claims)
            {
                sb.AppendFormat("{0}={1}&", HttpUtility.UrlEncode(kv.Key), HttpUtility.UrlEncode(kv.Value));
            }

            sb.AppendFormat("Issuer={0}&", HttpUtility.UrlEncode(swt.Issuer));
            sb.AppendFormat("Audience={0}&", HttpUtility.UrlEncode(swt.AudienceUri.AbsoluteUri));
            sb.AppendFormat("ExpiresOn={0:0}", swt.ValidTo.ToEpochTime());

            return sb.ToString();
        }
        /// <summary>
        /// Reads a serialized token and converts it into a <see cref="SecurityToken"/>.
        /// </summary>
        /// <param name="rawToken">The token in serialized form.</param>
        /// <returns>The parsed form of the token.</returns>
        public override SecurityToken ReadToken(string rawToken)
        {
            char   parameterSeparator = '&';
            Uri    audienceUri        = null;
            string issuer             = null;
            string signature          = null;
            string unsignedString     = null;
            string expires            = null;

            if (string.IsNullOrEmpty(rawToken))
            {
                throw new ArgumentNullException("rawToken");
            }

            //
            // Find the last parameter. The signature must be last per SWT specification.
            //
            int lastSeparator = rawToken.LastIndexOf(parameterSeparator);

            // Check whether the last parameter is an hmac.
            //
            if (lastSeparator > 0)
            {
                string lastParamStart = parameterSeparator + SwtConstants.Digest256 + "=";
                string lastParam      = rawToken.Substring(lastSeparator);

                // Strip the trailing hmac to obtain the original unsigned string for later hmac verification.
                // e.g. name1=value1&name2=value2&HMACSHA256=XXX123 -> name1=value1&name2=value2
                //
                if (lastParam.StartsWith(lastParamStart, StringComparison.Ordinal))
                {
                    unsignedString = rawToken.Substring(0, lastSeparator);
                }
            }
            else
            {
                throw new SecurityTokenValidationException("The Simple Web Token must have a signature at the end. The incoming token did not have a signature at the end of the token.");
            }

            // Signature is a mandatory parameter, and it must be the last one.
            // If there's no trailing hmac, Return error.
            //
            if (unsignedString == null)
            {
                throw new SecurityTokenValidationException("The Simple Web Token must have a signature at the end. The incoming token did not have a signature at the end of the token.");
            }

            // Create a collection of SWT claims
            //
            NameValueCollection rawClaims = ParseToken(rawToken);

            audienceUri = new Uri(rawClaims[SwtConstants.Audience]);
            if (audienceUri != null)
            {
                rawClaims.Remove(SwtConstants.Audience);
            }
            else
            {
                throw new SecurityTokenValidationException("Then incoming token does not have an AudienceUri.");
            }

            expires = rawClaims[SwtConstants.ExpiresOn];
            if (expires != null)
            {
                rawClaims.Remove(SwtConstants.ExpiresOn);
            }
            else
            {
                throw new SecurityTokenValidationException("Then incoming token does not have an expiry time.");
            }

            issuer = rawClaims[SwtConstants.Issuer];
            if (issuer != null)
            {
                rawClaims.Remove(SwtConstants.Issuer);
            }
            else
            {
                throw new SecurityTokenValidationException("Then incoming token does not have an Issuer");
            }

            signature = rawClaims[SwtConstants.Digest256];
            if (signature != null)
            {
                rawClaims.Remove(SwtConstants.Digest256);
            }
            else
            {
                throw new SecurityTokenValidationException("Then incoming token does not have a signature");
            }

            List <Claim> claims = DecodeClaims(issuer, rawClaims);

            SimpleWebToken swt = new SimpleWebToken(audienceUri, issuer, DecodeExpiry(expires), claims, signature, unsignedString);

            return(swt);
        }
 public SFSimpleWebToken(SimpleWebToken swt)
 {
     Container.Current.SatisfyImportsOnce(this);
     this.RawToken = WriteToken(swt);
     this.EnsureProperties();
 }
        internal static void CreateClaims(SimpleWebToken swt, StringBuilder sb)
        {
            var claims = new Dictionary<string, List<string>>();

            foreach (var claim in swt.Claims)
            {
                if (claims.ContainsKey(claim.Type))
                {
                    claims[claim.Type].Add(claim.Value);
                }
                else
                {
                    claims.Add(claim.Type, new List<string>());
                    claims[claim.Type].Add(claim.Value);
                }
            }

            foreach (var kv in claims)
            {
                var values = kv.Value;
                string s = null;

                foreach (var val in values)
                {
                    if (string.IsNullOrEmpty(s))
                    {
                        s = HttpUtility.UrlEncode(val);
                        continue;
                    }

                    s += string.Format(",{0}", HttpUtility.UrlEncode(val));
                }

                sb.AppendFormat("{0}={1}&", HttpUtility.UrlEncode(kv.Key), HttpUtility.UrlEncode(s));
            }
        }
        private static string CreateUnsignedToken(SimpleWebToken swt)
        {
            var sb = new StringBuilder();
            CreateClaims(swt, sb);

            sb.AppendFormat("Issuer={0}&", HttpUtility.UrlEncode(swt.Issuer));
            sb.AppendFormat("Audience={0}&", HttpUtility.UrlEncode(swt.AudienceUri.AbsoluteUri));
            sb.AppendFormat("ExpiresOn={0:0}", swt.ValidTo.ToEpochTime());

            return sb.ToString();
        }
        /// <summary>
        /// Reads a serialized token and converts it into a <see cref="SecurityToken"/>.
        /// </summary>
        /// <param name="rawToken">The token in serialized form.</param>
        /// <returns>The parsed form of the token.</returns>
        public SecurityToken ReadToken(string rawToken)
        {
            char parameterSeparator = '&';
            Uri audienceUri = null;
            string issuer = null;
            string signature = null;
            string unsignedString = null;
            string expires = null;

            if (string.IsNullOrEmpty(rawToken))
            {
                throw new ArgumentNullException("rawToken");
            }

            //
            // Find the last parameter. The signature must be last per SWT specification.
            //
            int lastSeparator = rawToken.LastIndexOf(parameterSeparator);

            // Check whether the last parameter is an hmac.
            //
            if (lastSeparator > 0)
            {
                string lastParamStart = parameterSeparator + SwtConstants.Digest256 + "=";
                string lastParam = rawToken.Substring(lastSeparator);

                // Strip the trailing hmac to obtain the original unsigned string for later hmac verification.
                // e.g. name1=value1&name2=value2&HMACSHA256=XXX123 -> name1=value1&name2=value2
                //
                if (lastParam.StartsWith(lastParamStart, StringComparison.Ordinal))
                {
                    unsignedString = rawToken.Substring(0, lastSeparator);
                }
            }
            else
            {
                throw new SecurityTokenValidationException("The Simple Web Token must have a signature at the end. The incoming token did not have a signature at the end of the token.");
            }

            // Signature is a mandatory parameter, and it must be the last one.
            // If there's no trailing hmac, Return error.
            //
            if (unsignedString == null)
            {
                throw new SecurityTokenValidationException("The Simple Web Token must have a signature at the end. The incoming token did not have a signature at the end of the token.");
            }

            // Create a collection of SWT claims
            //
            NameValueCollection rawClaims = ParseToken(rawToken);

            audienceUri = new Uri(rawClaims[SwtConstants.Audience]);
            if (audienceUri != null)
            {
                rawClaims.Remove(SwtConstants.Audience);
            }
            else
            {
                throw new SecurityTokenValidationException("Then incoming token does not have an AudienceUri.");
            }

            expires = rawClaims[SwtConstants.ExpiresOn];
            if (expires != null)
            {
                rawClaims.Remove(SwtConstants.ExpiresOn);
            }
            else
            {
                throw new SecurityTokenValidationException("Then incoming token does not have an expiry time.");
            }

            issuer = rawClaims[SwtConstants.Issuer];
            if (issuer != null)
            {
                rawClaims.Remove(SwtConstants.Issuer);
            }
            else
            {
                throw new SecurityTokenValidationException("Then incoming token does not have an Issuer");
            }

            signature = rawClaims[SwtConstants.Digest256];
            if (signature != null)
            {
                rawClaims.Remove(SwtConstants.Digest256);
            }
            else
            {
                throw new SecurityTokenValidationException("Then incoming token does not have a signature");
            }

            List<Claim> claims = DecodeClaims(issuer, rawClaims);

            SimpleWebToken swt = new SimpleWebToken(audienceUri, issuer, DecodeExpiry(expires), claims, signature, unsignedString);
            return swt;
        }
 /// <summary>
 /// Requests an SWT Token using an input SWT token.
 /// </summary>
 /// <param name="token">The input SWT token.</param>
 /// <param name="scope">The requested scope.</param>
 /// <returns>The requested SWT token</returns>
 public SimpleWebToken Issue(SimpleWebToken token, Uri scope)
 {
     return IssueAssertion(token.ToString(), "SWT", scope);
 }
        private string WriteToken(SimpleWebToken swt)
        {

            if (swt == null)
            {
                throw new InvalidOperationException("token");
            }

            var unsignedToken = CreateUnsignedToken(swt);

            var RP = RelyingPartyRepository.List(0, 100).First( b => b.Realm == swt.AudienceUri);

            var hexString = Convert.ToBase64String(RP.SymmetricSigningKey);

            var hmac = new HMACSHA256(SFHelper.HexToByte(hexString));
            var sig = hmac.ComputeHash(Encoding.ASCII.GetBytes(unsignedToken));

            var signedToken = String.Format("{0}&HMACSHA256={1}",
                unsignedToken,
                HttpUtility.UrlEncode(Convert.ToBase64String(sig)));

            return signedToken;
        }