/// <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); }
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; }