/// <summary> /// Reads and validates a well fromed Saml2 token. /// </summary> /// <param name="securityToken">A Saml2 token.</param> /// <param name="validationParameters">Contains data and information needed for validation.</param> /// <param name="validatedToken">The <see cref="SamlSecurityToken"/> that was validated.</param> /// <exception cref="ArgumentNullException">'securityToken' is null or whitespace.</exception> /// <exception cref="ArgumentNullException">'validationParameters' is null.</exception> /// <exception cref="ArgumentException">'securityToken.Length' > <see cref="MaximumTokenSizeInBytes"/>.</exception> /// <returns>A <see cref="ClaimsPrincipal"/> generated from the claims in the Saml2 securityToken.</returns> public virtual ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken) { validatedToken = null; if (string.IsNullOrWhiteSpace(securityToken)) { throw new ArgumentNullException("securityToken"); } if (validationParameters == null) { throw new ArgumentNullException("validationParameters"); } if (securityToken.Length > MaximumTokenSizeInBytes) { throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10209, securityToken.Length, MaximumTokenSizeInBytes)); } Saml2SecurityToken samlToken; using (StringReader sr = new StringReader(securityToken)) { using (XmlDictionaryReader reader = XmlDictionaryReader.CreateDictionaryReader(XmlReader.Create(sr))) { samlToken = (new Saml2Handler() { Configuration = new SecurityTokenHandlerConfiguration { IssuerTokenResolver = new SecurityKeyResolver(securityToken, validationParameters), MaxClockSkew = validationParameters.ClockSkew, ServiceTokenResolver = SecurityTokenResolver.CreateDefaultSecurityTokenResolver(validationParameters.ClientDecryptionTokens, true), } }).ReadToken(reader) as Saml2SecurityToken; } } if (samlToken.IssuerToken == null && validationParameters.RequireSignedTokens) { throw new SecurityTokenValidationException(ErrorMessages.IDX10213); } if (samlToken.Assertion == null) { throw new ArgumentException(ErrorMessages.IDX10202); } DateTime?notBefore = null; DateTime?expires = null; if (samlToken.Assertion.Conditions != null) { notBefore = samlToken.Assertion.Conditions.NotBefore; expires = samlToken.Assertion.Conditions.NotOnOrAfter; } Validators.ValidateTokenReplay(securityToken, expires, validationParameters); if (validationParameters.ValidateLifetime) { if (validationParameters.LifetimeValidator != null) { if (!validationParameters.LifetimeValidator(notBefore: notBefore, expires: expires, securityToken: samlToken, validationParameters: validationParameters)) { throw new SecurityTokenInvalidLifetimeException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10230, securityToken)); } } else { ValidateLifetime(notBefore: notBefore, expires: expires, securityToken: samlToken, validationParameters: validationParameters); } } // TODO // need to validate ValidateConfirmationData(subjectConfirmation.SubjectConfirmationData); if (validationParameters.ValidateAudience) { List <string> audiences = new List <string>(); if (samlToken.Assertion.Conditions != null && samlToken.Assertion.Conditions.AudienceRestrictions != null) { foreach (Saml2AudienceRestriction restriction in samlToken.Assertion.Conditions.AudienceRestrictions) { if (restriction == null) { continue; } foreach (Uri uri in restriction.Audiences) { if (uri == null) { continue; } audiences.Add(uri.OriginalString); } } } if (validationParameters.AudienceValidator != null) { if (!validationParameters.AudienceValidator(audiences, samlToken, validationParameters)) { throw new SecurityTokenInvalidAudienceException(string.Format(CultureInfo.InvariantCulture, ErrorMessages.IDX10231, securityToken)); } } else { ValidateAudience(audiences, samlToken, validationParameters); } } string issuer = samlToken.Assertion.Issuer != null ? samlToken.Assertion.Issuer.Value : null; if (validationParameters.ValidateIssuer) { if (validationParameters.IssuerValidator != null) { issuer = validationParameters.IssuerValidator(issuer, samlToken, validationParameters); } else { issuer = ValidateIssuer(issuer, samlToken, validationParameters); } } if (samlToken.IssuerToken != null) { ValidateIssuerSecurityKey(samlToken.IssuerToken.SecurityKeys[0], samlToken, validationParameters); } ClaimsIdentity identity = CreateClaimsIdentity(samlToken, issuer, validationParameters); if (validationParameters.SaveSigninToken) { identity.BootstrapContext = new BootstrapContext(securityToken); } validatedToken = samlToken; return(new ClaimsPrincipal(identity)); }
/// <summary> /// Determines if an issuer found in a <see cref="SecurityToken"/> is valid. /// </summary> /// <param name="issuer">The issuer to validate</param> /// <param name="securityToken">The <see cref="SecurityToken"/> that is being validated.</param> /// <param name="validationParameters"><see cref="TokenValidationParameters"/> required for validation.</param> /// <returns>The issuer to use when creating the "Claim"(s) in a "ClaimsIdentity".</returns> /// <exception cref="ArgumentNullException">If 'vaidationParameters' is null.</exception> /// <exception cref="ArgumentNullException">If 'issuer' is null or whitespace and <see cref="TokenValidationParameters.ValidateIssuer"/> is true.</exception> /// <exception cref="SecurityTokenInvalidIssuerException">If <see cref="TokenValidationParameters.ValidIssuer"/> is null or whitespace and <see cref="TokenValidationParameters.ValidIssuers"/> is null.</exception> /// <exception cref="SecurityTokenInvalidIssuerException">If 'issuer' failed to matched either <see cref="TokenValidationParameters.ValidIssuer"/> or one of <see cref="TokenValidationParameters.ValidIssuers"/>.</exception> /// <remarks>An EXACT match is required.</remarks> public static string ValidateIssuer(string issuer, SecurityToken securityToken, TokenValidationParameters validationParameters) { if (validationParameters == null) { throw LogHelper.LogArgumentNullException(nameof(validationParameters)); } if (validationParameters.IssuerValidator != null) { return(validationParameters.IssuerValidator(issuer, securityToken, validationParameters)); } if (!validationParameters.ValidateIssuer) { LogHelper.LogInformation(LogMessages.IDX10235); return(issuer); } if (string.IsNullOrWhiteSpace(issuer)) { throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidIssuerException(LogMessages.IDX10211) { InvalidIssuer = issuer }); } // Throw if all possible places to validate against are null or empty if (string.IsNullOrWhiteSpace(validationParameters.ValidIssuer) && (validationParameters.ValidIssuers == null)) { throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidIssuerException(LogMessages.IDX10204) { InvalidIssuer = issuer }); } if (string.Equals(validationParameters.ValidIssuer, issuer, StringComparison.Ordinal)) { LogHelper.LogInformation(LogMessages.IDX10236, issuer); return(issuer); } if (null != validationParameters.ValidIssuers) { foreach (string str in validationParameters.ValidIssuers) { if (string.IsNullOrEmpty(str)) { LogHelper.LogInformation(LogMessages.IDX10235); continue; } if (string.Equals(str, issuer, StringComparison.Ordinal)) { LogHelper.LogInformation(LogMessages.IDX10236, issuer); return(issuer); } } } throw LogHelper.LogExceptionMessage( new SecurityTokenInvalidIssuerException(LogHelper.FormatInvariant(LogMessages.IDX10205, issuer, (validationParameters.ValidIssuer ?? "null"), Utility.SerializeAsSingleCommaDelimitedString(validationParameters.ValidIssuers))) { InvalidIssuer = issuer }); }