/// <summary>
        /// Validates an <see cref="X509SecurityToken"/>.
        /// </summary>
        /// <param name="token">The <see cref="X509SecurityToken"/> to validate.</param>
        /// <returns>A <see cref="ReadOnlyCollection{T}"/> of <see cref="ClaimsIdentity"/> representing the identities contained in the token.</returns>
        /// <exception cref="ArgumentNullException">The parameter 'token' is null.</exception>
        /// <exception cref="ArgumentException">The token is not assignable from <see cref="X509SecurityToken"/>.</exception>
        /// <exception cref="InvalidOperationException">Configuration <see cref="SecurityTokenHandlerConfiguration"/>is null.</exception>
        /// <exception cref="SecurityTokenValidationException">The current <see cref="X509CertificateValidator"/> was unable to validate the certificate in the Token.</exception>
        /// <exception cref="InvalidOperationException">Configuration.IssuerNameRegistry is null.</exception>
        /// <exception cref="SecurityTokenException">Configuration.IssuerNameRegistry return null when resolving the issuer of the certificate in the Token.</exception>
        public override ReadOnlyCollection<ClaimsIdentity> ValidateToken(SecurityToken token)
        {
            if (token == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("token");
            }

            X509SecurityToken x509Token = token as X509SecurityToken;
            if (x509Token == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("token", SR.GetString(SR.ID0018, typeof(X509SecurityToken)));
            }

            if (this.Configuration == null)
            {
                throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4274));
            }

            try
            {
                // Validate the token.
                try
                {
                    this.CertificateValidator.Validate(x509Token.Certificate);
                }
                catch (SecurityTokenValidationException e)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenValidationException(SR.GetString(SR.ID4257,
                        X509Util.GetCertificateId(x509Token.Certificate)), e));
                }

                if (this.Configuration.IssuerNameRegistry == null)
                {
                    throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4277));
                }

                string issuer = X509Util.GetCertificateIssuerName(x509Token.Certificate, this.Configuration.IssuerNameRegistry);
                if (String.IsNullOrEmpty(issuer))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4175)));
                }

                ClaimsIdentity identity = null;

                if (!mapToWindows)
                {
                    identity = new ClaimsIdentity(AuthenticationTypes.X509);

                    // PARTIAL TRUST: will fail when adding claims, AddClaim is SecurityCritical.
                    identity.AddClaim(new Claim(ClaimTypes.AuthenticationMethod, AuthenticationMethods.X509));
                }
                else
                {
                    WindowsIdentity windowsIdentity;
                    X509WindowsSecurityToken x509WindowsSecurityToken = token as X509WindowsSecurityToken;

                    // if this is the case, then the user has already been mapped to a windows account, just return the identity after adding a couple of claims.
                    if (x509WindowsSecurityToken != null && x509WindowsSecurityToken.WindowsIdentity != null)
                    {
                        // X509WindowsSecurityToken is disposable, make a copy.
                        windowsIdentity = new WindowsIdentity(x509WindowsSecurityToken.WindowsIdentity.Token, x509WindowsSecurityToken.AuthenticationType);
                    }
                    else
                    {
                        // Ensure NT_AUTH chain policy for certificate account mapping
                        if (this.x509NTAuthChainTrustValidator == null)
                        {
                            lock (this.lockObject)
                            {
                                if (this.x509NTAuthChainTrustValidator == null)
                                {
                                    this.x509NTAuthChainTrustValidator = new X509NTAuthChainTrustValidator();
                                }
                            }
                        }

                        this.x509NTAuthChainTrustValidator.Validate(x509Token.Certificate);
                        windowsIdentity = ClaimsHelper.CertificateLogon(x509Token.Certificate);
                    }

                    // PARTIAL TRUST: will fail when adding claims, AddClaim is SecurityCritical.
                    windowsIdentity.AddClaim(new Claim(ClaimTypes.AuthenticationMethod, AuthenticationMethods.X509));
                    identity = windowsIdentity;
                }

                if (this.Configuration.SaveBootstrapContext)
                {
                    identity.BootstrapContext = new BootstrapContext(token, this);
                }

                identity.AddClaim(new Claim(ClaimTypes.AuthenticationInstant, XmlConvert.ToString(DateTime.UtcNow, DateTimeFormats.Generated), ClaimValueTypes.DateTime));
                identity.AddClaims(X509Util.GetClaimsFromCertificate(x509Token.Certificate, issuer));

                this.TraceTokenValidationSuccess(token);

                List<ClaimsIdentity> identities = new List<ClaimsIdentity>(1);
                identities.Add(identity);
                return identities.AsReadOnly();
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e))
                {
                    throw;
                }

                this.TraceTokenValidationFailure(token, e.Message);
                throw e;
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Validates an <see cref="X509SecurityToken"/>.
        /// </summary>
        /// <param name="token">The <see cref="X509SecurityToken"/> to validate.</param>
        /// <returns>A <see cref="ReadOnlyCollection{T}"/> of <see cref="ClaimsIdentity"/> representing the identities contained in the token.</returns>
        /// <exception cref="ArgumentNullException">The parameter 'token' is null.</exception>
        /// <exception cref="ArgumentException">The token is not assignable from <see cref="X509SecurityToken"/>.</exception>
        /// <exception cref="InvalidOperationException">Configuration <see cref="SecurityTokenHandlerConfiguration"/>is null.</exception>
        /// <exception cref="SecurityTokenValidationException">The current <see cref="X509CertificateValidator"/> was unable to validate the certificate in the Token.</exception>
        /// <exception cref="InvalidOperationException">Configuration.IssuerNameRegistry is null.</exception>
        /// <exception cref="SecurityTokenException">Configuration.IssuerNameRegistry return null when resolving the issuer of the certificate in the Token.</exception>
        public override ReadOnlyCollection <ClaimsIdentity> ValidateToken(SecurityToken token)
        {
            if (token == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("token");
            }

            X509SecurityToken x509Token = token as X509SecurityToken;

            if (x509Token == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("token", SR.GetString(SR.ID0018, typeof(X509SecurityToken)));
            }

            if (this.Configuration == null)
            {
                throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4274));
            }

            try
            {
                // Validate the token.
                try
                {
                    this.CertificateValidator.Validate(x509Token.Certificate);
                }
                catch (SecurityTokenValidationException e)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenValidationException(SR.GetString(SR.ID4257,
                                                                                                                                X509Util.GetCertificateId(x509Token.Certificate)), e));
                }

                if (this.Configuration.IssuerNameRegistry == null)
                {
                    throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4277));
                }

                string issuer = X509Util.GetCertificateIssuerName(x509Token.Certificate, this.Configuration.IssuerNameRegistry);
                if (String.IsNullOrEmpty(issuer))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4175)));
                }

                ClaimsIdentity identity = null;

                if (!mapToWindows)
                {
                    identity = new ClaimsIdentity(AuthenticationTypes.X509);

                    // PARTIAL TRUST: will fail when adding claims, AddClaim is SecurityCritical.
                    identity.AddClaim(new Claim(ClaimTypes.AuthenticationMethod, AuthenticationMethods.X509));
                }
                else
                {
                    WindowsIdentity          windowsIdentity;
                    X509WindowsSecurityToken x509WindowsSecurityToken = token as X509WindowsSecurityToken;

                    // if this is the case, then the user has already been mapped to a windows account, just return the identity after adding a couple of claims.
                    if (x509WindowsSecurityToken != null && x509WindowsSecurityToken.WindowsIdentity != null)
                    {
                        // X509WindowsSecurityToken is disposable, make a copy.
                        windowsIdentity = new WindowsIdentity(x509WindowsSecurityToken.WindowsIdentity.Token, x509WindowsSecurityToken.AuthenticationType);
                    }
                    else
                    {
                        // Ensure NT_AUTH chain policy for certificate account mapping
                        if (this.x509NTAuthChainTrustValidator == null)
                        {
                            lock (this.lockObject)
                            {
                                if (this.x509NTAuthChainTrustValidator == null)
                                {
                                    this.x509NTAuthChainTrustValidator = new X509NTAuthChainTrustValidator();
                                }
                            }
                        }

                        this.x509NTAuthChainTrustValidator.Validate(x509Token.Certificate);
                        windowsIdentity = ClaimsHelper.CertificateLogon(x509Token.Certificate);
                    }

                    // PARTIAL TRUST: will fail when adding claims, AddClaim is SecurityCritical.
                    windowsIdentity.AddClaim(new Claim(ClaimTypes.AuthenticationMethod, AuthenticationMethods.X509));
                    identity = windowsIdentity;
                }

                if (this.Configuration.SaveBootstrapContext)
                {
                    identity.BootstrapContext = new BootstrapContext(token, this);
                }

                identity.AddClaim(new Claim(ClaimTypes.AuthenticationInstant, XmlConvert.ToString(DateTime.UtcNow, DateTimeFormats.Generated), ClaimValueTypes.DateTime));
                identity.AddClaims(X509Util.GetClaimsFromCertificate(x509Token.Certificate, issuer));

                this.TraceTokenValidationSuccess(token);

                List <ClaimsIdentity> identities = new List <ClaimsIdentity>(1);
                identities.Add(identity);
                return(identities.AsReadOnly());
            }
            catch (Exception e)
            {
                if (Fx.IsFatal(e))
                {
                    throw;
                }

                this.TraceTokenValidationFailure(token, e.Message);
                throw e;
            }
        }