// </Snippet8> // <Snippet9> /// <summary> /// This method validates the Simple Web Token. /// </summary> /// <param name="token">A simple web token.</param> /// <returns>A Claims Collection which contains all the claims from the token.</returns> public override ReadOnlyCollection <ClaimsIdentity> ValidateToken(SecurityToken token) { if (token == null) { throw new ArgumentNullException("token"); } SimpleWebToken simpleWebToken = token as SimpleWebToken; if (simpleWebToken == null) { throw new ArgumentException("The token provided must be of type SimpleWebToken."); } if (DateTime.Compare(simpleWebToken.ValidTo.Add(Configuration.MaxClockSkew), DateTime.UtcNow) <= 0) { throw new SecurityTokenExpiredException("The incoming token has expired. Get a new access token from the Authorization Server."); } ValidateSignature(simpleWebToken); ValidateAudience(simpleWebToken.Audience); ClaimsIdentity claimsIdentity = CreateClaims(simpleWebToken); if (this.Configuration.SaveBootstrapContext) { claimsIdentity.BootstrapContext = new BootstrapContext(simpleWebToken.SerializedToken); } List <ClaimsIdentity> claimCollection = new List <ClaimsIdentity>(new ClaimsIdentity[] { claimsIdentity }); return(claimCollection.AsReadOnly()); }
// </Snippet7> // <Snippet8> /// <summary> /// Parse the string token and generates a <see cref="SecurityToken"/>. /// </summary> /// <param name="serializedToken">The serialized form of the token received.</param> /// <returns>The parsed form of the token.</returns> protected SecurityToken ReadSecurityTokenFromString(string serializedToken) { if (String.IsNullOrEmpty(serializedToken)) { throw new ArgumentException("The parameter 'serializedToken' cannot be null or empty string."); } // Create a collection of SWT name value pairs NameValueCollection properties = ParseToken(serializedToken); SimpleWebToken swt = new SimpleWebToken(properties, serializedToken); return(swt); }
// </Snippet11> // <Snippet12> /// <summary> /// Validates the signature on the incoming token. /// </summary> /// <param name="simpleWebToken">The incoming <see cref="SimpleWebToken"/>.</param> protected virtual void ValidateSignature(SimpleWebToken simpleWebToken) { if (simpleWebToken == null) { throw new ArgumentNullException("simpleWebToken"); } if (String.IsNullOrEmpty(simpleWebToken.SerializedToken) || String.IsNullOrEmpty(simpleWebToken.Signature)) { throw new SecurityTokenValidationException("The token does not have a signature to verify"); } string serializedToken = simpleWebToken.SerializedToken; string unsignedToken = null; // Find the last parameter. The signature must be last per SWT specification. int lastSeparator = serializedToken.LastIndexOf(ParameterSeparator); // Check whether the last parameter is an hmac. if (lastSeparator > 0) { string lastParamStart = ParameterSeparator + SimpleWebTokenConstants.Signature + "="; string lastParam = serializedToken.Substring(lastSeparator); // Strip the trailing hmac to obtain the original unsigned string for later hmac verification. if (lastParam.StartsWith(lastParamStart, StringComparison.Ordinal)) { unsignedToken = serializedToken.Substring(0, lastSeparator); } } SimpleWebTokenKeyIdentifierClause clause = new SimpleWebTokenKeyIdentifierClause(simpleWebToken.Audience); InMemorySymmetricSecurityKey securityKey = null; try { securityKey = (InMemorySymmetricSecurityKey)this.Configuration.IssuerTokenResolver.ResolveSecurityKey(clause); } catch (InvalidOperationException) { throw new SecurityTokenValidationException("A Symmetric key was not found for the given key identifier clause."); } string generatedSignature = GenerateSignature(unsignedToken, securityKey.GetSymmetricKey()); if (string.CompareOrdinal(generatedSignature, simpleWebToken.Signature) != 0) { throw new SecurityTokenValidationException("The signature on the incoming token is invalid."); } }
// </Snippet14> // <Snippet15> /// <summary>Creates <see cref="Claim"/>'s from the incoming token. /// </summary> /// <param name="simpleWebToken">The incoming <see cref="SimpleWebToken"/>.</param> /// <returns>A <see cref="ClaimsIdentity"/> created from the token.</returns> protected virtual ClaimsIdentity CreateClaims(SimpleWebToken simpleWebToken) { if (simpleWebToken == null) { throw new ArgumentNullException("simpleWebToken"); } NameValueCollection tokenProperties = simpleWebToken.GetAllProperties(); if (tokenProperties == null) { throw new SecurityTokenValidationException("No claims can be created from this Simple Web Token."); } if (Configuration.IssuerNameRegistry == null) { throw new InvalidOperationException("The Configuration.IssuerNameRegistry property of this SecurityTokenHandler is set to null. Tokens cannot be validated in this state."); } string normalizedIssuer = Configuration.IssuerNameRegistry.GetIssuerName(simpleWebToken); ClaimsIdentity identity = new ClaimsIdentity(AuthenticationTypes.Federation); foreach (string key in tokenProperties.Keys) { if (!IsReservedKeyName(key) && !string.IsNullOrEmpty(tokenProperties[key])) { identity.AddClaim(new Claim(key, tokenProperties[key], ClaimValueTypes.String, normalizedIssuer)); if (key == AcsNameClaimType) { // add a default name claim from the Name identifier claim. identity.AddClaim(new Claim(DefaultNameClaimType, tokenProperties[key], ClaimValueTypes.String, normalizedIssuer)); } } } return(identity); }
// </Snippet3> // <Snippet4> public override SecurityToken CreateToken(SecurityTokenDescriptor tokenDescriptor) { if (tokenDescriptor == null) { throw new ArgumentNullException("tokenDescriptor"); } NameValueCollection properties = new NameValueCollection(); properties.Add(SimpleWebTokenConstants.Id, Guid.NewGuid().ToString()); properties.Add(SimpleWebTokenConstants.Issuer, tokenDescriptor.TokenIssuerName); properties.Add(SimpleWebTokenConstants.Audience, tokenDescriptor.AppliesToAddress); properties.Add(SimpleWebTokenConstants.ExpiresOn, SecondsFromSwtBaseTime(tokenDescriptor.Lifetime.Expires)); properties.Add(SimpleWebTokenConstants.ValidFrom, SecondsFromSwtBaseTime(tokenDescriptor.Lifetime.Created)); foreach (Claim claim in tokenDescriptor.Subject.Claims) { properties.Add(claim.Type, claim.Value); } SimpleWebToken token = new SimpleWebToken(properties); return(token); }
// </Snippet9> // <Snippet10> /// <summary> /// Serializes the given SecurityToken to the XmlWriter. /// </summary> /// <param name="writer">XmlWriter into which the token is serialized.</param> /// <param name="token">SecurityToken to be serialized.</param> public override void WriteToken(XmlWriter writer, SecurityToken token) { SimpleWebToken simpleWebToken = token as SimpleWebToken; if (simpleWebToken == null) { throw new SecurityTokenException("The given token is not of the expected type 'SimpleWebToken'."); } string signedToken = null; if (String.IsNullOrEmpty(simpleWebToken.SerializedToken)) { StringBuilder strBuilder = new StringBuilder(); bool skipDelimiter = true; NameValueCollection tokenProperties = simpleWebToken.GetAllProperties(); // remove the signature if present if (String.IsNullOrEmpty(tokenProperties[SimpleWebTokenConstants.Signature])) { tokenProperties.Remove(SimpleWebTokenConstants.Signature); } foreach (string key in tokenProperties.Keys) { if (tokenProperties[key] != null) { if (!skipDelimiter) { strBuilder.Append(ParameterSeparator); } strBuilder.Append(String.Format( CultureInfo.InvariantCulture, "{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(tokenProperties[key]))); skipDelimiter = false; } } string serializedToken = strBuilder.ToString(); SimpleWebTokenKeyIdentifierClause clause = new SimpleWebTokenKeyIdentifierClause(simpleWebToken.Audience); InMemorySymmetricSecurityKey securityKey = null; try { securityKey = (InMemorySymmetricSecurityKey)this.Configuration.IssuerTokenResolver.ResolveSecurityKey(clause); } catch (InvalidOperationException) { throw new SecurityTokenValidationException("A Symmetric key was not found for the given key identifier clause."); } // append the signature string signature = GenerateSignature(serializedToken, securityKey.GetSymmetricKey()); strBuilder.Append(String.Format( CultureInfo.InvariantCulture, "{0}{1}={2}", ParameterSeparator, HttpUtility.UrlEncode(SimpleWebTokenConstants.Signature), HttpUtility.UrlEncode(signature))); signedToken = strBuilder.ToString(); } else { // reuse the stored serialized token if present signedToken = simpleWebToken.SerializedToken; } string encodedToken = Convert.ToBase64String(Encoding.UTF8.GetBytes(signedToken)); writer.WriteStartElement(BinarySecurityToken); writer.WriteAttributeString("Id", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", token.Id); writer.WriteAttributeString(ValueType, SimpleWebTokenConstants.ValueTypeUri); writer.WriteAttributeString(EncodingType, Base64EncodingType); writer.WriteString(encodedToken); writer.WriteEndElement(); }