SecurityTokenHandler.ValidateToken(SecurityToken) Método
Definición
Importante
Parte de la información hace referencia a la versión preliminar del producto, que puede haberse modificado sustancialmente antes de lanzar la versión definitiva. Microsoft no otorga ninguna garantía, explícita o implícita, con respecto a la información proporcionada aquí.
Cuando se reemplaza en una clase derivada, valida el token de seguridad especificado. El token debe ser del tipo procesado por la clase derivada.
public:
virtual System::Collections::ObjectModel::ReadOnlyCollection<System::Security::Claims::ClaimsIdentity ^> ^ ValidateToken(System::IdentityModel::Tokens::SecurityToken ^ token);
public virtual System.Collections.ObjectModel.ReadOnlyCollection<System.Security.Claims.ClaimsIdentity> ValidateToken (System.IdentityModel.Tokens.SecurityToken token);
abstract member ValidateToken : System.IdentityModel.Tokens.SecurityToken -> System.Collections.ObjectModel.ReadOnlyCollection<System.Security.Claims.ClaimsIdentity>
override this.ValidateToken : System.IdentityModel.Tokens.SecurityToken -> System.Collections.ObjectModel.ReadOnlyCollection<System.Security.Claims.ClaimsIdentity>
Public Overridable Function ValidateToken (token As SecurityToken) As ReadOnlyCollection(Of ClaimsIdentity)
Parámetros
- token
- SecurityToken
Token que se va a validar.
Devoluciones
Identidades contenidas en el token.
Ejemplos
En el código siguiente se muestra una invalidación del ValidateToken método para un controlador de tokens de seguridad que procesa tokens web simples (SWT). El código se toma del CustomToken
ejemplo. Para obtener información sobre este ejemplo y otros ejemplos disponibles para WIF y dónde descargarlos, consulte Índice de ejemplo de código wif.
/// <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();
}
El código siguiente muestra CreateClaims
el método que se invoca a partir de la invalidación del ValidateToken método en el ejemplo anterior. Este método devuelve un ClaimsIdentity objeto que se crea a partir de las notificaciones del token. El código se toma del CustomToken
ejemplo. Para obtener información sobre este ejemplo y otros ejemplos disponibles para WIF y dónde descargarlos, consulte Índice de ejemplo de código wif.
/// <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;
}
El código siguiente muestra ValidateSignature
el método que se invoca desde la invalidación del ValidateToken método en el controlador de token web simple. Este método valida la firma en el token mediante el configurado IssuerTokenResolver. El código se toma del CustomToken
ejemplo. Para obtener información sobre este ejemplo y otros ejemplos disponibles para WIF y dónde descargarlos, consulte Índice de ejemplo de código wif.
/// <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.") ;
}
}
/// <summary>
/// Generates an HMACSHA256 signature for a given string and key.
/// </summary>
/// <param name="unsignedToken">The token to be signed.</param>
/// <param name="signingKey">The key used to generate the signature.</param>
/// <returns>The generated signature.</returns>
protected static string GenerateSignature(string unsignedToken, byte[] signingKey)
{
using (HMACSHA256 hmac = new HMACSHA256(signingKey))
{
byte[] signatureBytes = hmac.ComputeHash(Encoding.ASCII.GetBytes(unsignedToken));
string signature = HttpUtility.UrlEncode(Convert.ToBase64String(signatureBytes));
return signature;
}
}
El código siguiente muestra ValidateAudience
el método que se invoca desde la invalidación del ValidateToken método en el controlador de token web simple. Este método valida la audiencia contenida en el token con los URI de audiencia que se especificaron en la configuración. El código se toma del CustomToken
ejemplo. Para obtener información sobre este ejemplo y otros ejemplos disponibles para WIF y dónde descargarlos, consulte Índice de ejemplo de código wif.
/// <summary>
/// Validates the audience of the incoming token with those specified in configuration.
/// </summary>
/// <param name="tokenAudience">The audience of the incoming token.</param>
protected virtual void ValidateAudience( string tokenAudience )
{
if ( Configuration.AudienceRestriction.AudienceMode != AudienceUriMode.Never )
{
if ( String.IsNullOrEmpty( tokenAudience ) )
{
throw new SecurityTokenValidationException("The incoming token does not have a valid audience Uri and the Audience Restriction is not set to 'None'.");
}
if ( Configuration.AudienceRestriction.AllowedAudienceUris.Count == 0 )
{
throw new InvalidOperationException( " Audience Restriction is not set to 'None' but no valid audience URI's are configured." );
}
IList<Uri> allowedAudienceUris = Configuration.AudienceRestriction.AllowedAudienceUris;
Uri audienceUri = null;
Uri.TryCreate(tokenAudience, UriKind.RelativeOrAbsolute, out audienceUri);
// Strip off any query string or fragment.
Uri audienceLeftPart;
if ( audienceUri.IsAbsoluteUri )
{
audienceLeftPart = new Uri( audienceUri.GetLeftPart( UriPartial.Path ) );
}
else
{
Uri baseUri = new Uri( "http://www.example.com" );
Uri resolved = new Uri( baseUri, tokenAudience );
audienceLeftPart = baseUri.MakeRelativeUri( new Uri( resolved.GetLeftPart( UriPartial.Path ) ) );
}
if ( !allowedAudienceUris.Contains( audienceLeftPart ) )
{
throw new AudienceUriValidationFailedException(
"The Audience Uri of the incoming token is not present in the list of permitted Audience Uri's.");
}
}
}
Comentarios
De forma predeterminada, este método produce una NotImplementedException excepción.
La ValidateToken infraestructura llama al método para validar y extraer las notificaciones del token de seguridad deserializado. Estas notificaciones se devuelven en la colección de ClaimsIdentity objetos devueltos por el método . En el caso típico, esta colección contendrá una única identidad.
En las clases derivadas, la validación normalmente incluye validar la audiencia prevista especificada en el token con los URI de audiencia especificados en la SecurityTokenHandlerConfiguration.AudienceRestriction propiedad del objeto de configuración del controlador de tokens especificado en la Configuration propiedad . Normalmente, estos URI se establecen en el archivo de configuración bajo el <elemento audienceUris> . Si no se puede validar la audiencia, se debe producir una AudienceUriValidationFailedException excepción.
Al procesar el token, el emisor se valida normalmente pasando el token del emisor a uno de los GetIssuerName métodos del IssuerNameRegistry objeto configurado para el controlador a través de la Configuration propiedad . El registro de nombres del emisor se configura normalmente a través del <elemento issuerNameRegistry> en el archivo de configuración. GetIssuerName devuelve el nombre del emisor. Este nombre se debe usar para establecer la Claim.Issuer propiedad en las notificaciones contenidas en el token. Si el registro de nombres de emisor no contiene una entrada para el token del emisor, GetIssuerName devuelve null
. En este caso, normalmente se produce una SecurityTokenException excepción en clases derivadas, pero este comportamiento es hasta el diseñador de la clase .