/// <summary>
        /// Initializes a new instance of the <see cref="OidcClient"/> class.
        /// </summary>
        /// <param name="options">The options.</param>
        public OidcClient(OidcClientOptions options)
        {
            _authorizeClient = new AuthorizeClient(options);
            _validator       = new ResponseValidator(options);

            _options = options;
        }
        public ResponseProcessor(OidcClientOptions options, Func <CancellationToken, Task> refreshKeysAsync)
        {
            _options          = options;
            _refreshKeysAsync = refreshKeysAsync;
            _logger           = options.LoggerFactory.CreateLogger <ResponseProcessor>();

            _crypto = new CryptoHelper(options);
        }
        public ResponseProcessor(OidcClientOptions options, Func <Task> refreshKeysAsync)
        {
            _options          = options;
            _refreshKeysAsync = refreshKeysAsync;
            _logger           = options.LoggerFactory.CreateLogger <ResponseProcessor>();

            _tokenValidator = new IdentityTokenValidator(options, refreshKeysAsync);
            _crypto         = new CryptoHelper(options);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="OidcClient"/> class.
        /// </summary>
        /// <param name="options">The options.</param>
        /// <exception cref="System.ArgumentNullException">options</exception>
        public OidcClient(OidcClientOptions options)
        {
            if (options == null) throw new ArgumentNullException(nameof(options));

            if (options.ProviderInformation == null)
            {
                if (options.Authority.IsMissing()) throw new ArgumentException("No authority specified", nameof(_options.Authority));
                useDiscovery = true;
            }

            _options = options;
            _logger = options.LoggerFactory.CreateLogger<OidcClient>();
            _authorizeClient = new AuthorizeClient(options);
            _processor = new ResponseProcessor(options, EnsureProviderInformationAsync);
        }
예제 #5
0
        /// <inheritdoc />
#pragma warning disable 1998
        public async Task <IdentityTokenValidationResult> ValidateAsync(string identityToken, OidcClientOptions options, CancellationToken cancellationToken = default)
#pragma warning restore 1998
        {
            var logger = options.LoggerFactory.CreateLogger <JwtHandlerIdentityTokenValidator>();

            logger.LogTrace("Validate");

            // setup general validation parameters
            var parameters = new TokenValidationParameters
            {
                ValidIssuer    = options.ProviderInformation.IssuerName,
                ValidAudience  = options.ClientId,
                ValidateIssuer = options.Policy.ValidateTokenIssuerName,
                NameClaimType  = JwtClaimTypes.Name,
                RoleClaimType  = JwtClaimTypes.Role,

                ClockSkew = options.ClockSkew
            };

            // read the token signing algorithm
            var          handler = new JsonWebTokenHandler();
            JsonWebToken jwt;

            try
            {
                jwt = handler.ReadJsonWebToken(identityToken);
            }
            catch (Exception ex)
            {
                return(new IdentityTokenValidationResult
                {
                    Error = $"Error validating identity token: {ex.ToString()}"
                });
            }

            var algorithm = jwt.Alg;

            // if token is unsigned, and this is allowed, skip signature validation
            if (string.Equals(algorithm, "none", StringComparison.OrdinalIgnoreCase))
            {
                if (options.Policy.RequireIdentityTokenSignature)
                {
                    return(new IdentityTokenValidationResult
                    {
                        Error = $"Identity token is not signed. Signatures are required by policy"
                    });
                }
                else
                {
                    logger.LogInformation("Identity token is not signed. This is allowed by configuration.");
                    parameters.RequireSignedTokens = false;
                }
            }
            else
            {
                // check if signature algorithm is allowed by policy
                if (!options.Policy.ValidSignatureAlgorithms.Contains(algorithm))
                {
                    return(new IdentityTokenValidationResult
                    {
                        Error = $"Identity token uses invalid algorithm: {algorithm}"
                    });
                }
                ;
            }

            var result = ValidateSignature(identityToken, handler, parameters, options, logger);

            if (result.IsValid == false)
            {
                if (result.Exception is SecurityTokenSignatureKeyNotFoundException)
                {
                    logger.LogWarning("Key for validating token signature cannot be found. Refreshing keyset.");

                    return(new IdentityTokenValidationResult
                    {
                        Error = "invalid_signature"
                    });
                }

                if (result.Exception is SecurityTokenUnableToValidateException)
                {
                    return(new IdentityTokenValidationResult
                    {
                        Error = "unable_to_validate_token"
                    });
                }

                throw result.Exception;
            }

            var user = new ClaimsPrincipal(result.ClaimsIdentity);

            var error = CheckRequiredClaim(user);

            if (error.IsPresent())
            {
                return(new IdentityTokenValidationResult
                {
                    Error = error
                });
            }

            return(new IdentityTokenValidationResult
            {
                User = user,
                SignatureAlgorithm = algorithm
            });
        }
예제 #6
0
        private TokenValidationResult ValidateSignature(string identityToken, JsonWebTokenHandler handler, TokenValidationParameters parameters, OidcClientOptions options, ILogger logger)
        {
            if (parameters.RequireSignedTokens)
            {
                // read keys from provider information
                var keys = new List <SecurityKey>();

                foreach (var webKey in options.ProviderInformation.KeySet.Keys)
                {
                    if (webKey.E.IsPresent() && webKey.N.IsPresent())
                    {
                        // only add keys used for signatures
                        if (webKey.Use == "sig" || webKey.Use == null)
                        {
                            var e = Base64Url.Decode(webKey.E);
                            var n = Base64Url.Decode(webKey.N);

                            var key = new RsaSecurityKey(new RSAParameters {
                                Exponent = e, Modulus = n
                            });
                            key.KeyId = webKey.Kid;

                            keys.Add(key);

                            logger.LogDebug("Added signing key with kid: {kid}", key?.KeyId ?? "not set");
                        }
                    }
                    else if (webKey.X.IsPresent() && webKey.Y.IsPresent() && webKey.Crv.IsPresent())
                    {
                        var ec = ECDsa.Create(new ECParameters
                        {
                            Curve = GetCurveFromCrvValue(webKey.Crv),
                            Q     = new ECPoint
                            {
                                X = Base64Url.Decode(webKey.X),
                                Y = Base64Url.Decode(webKey.Y)
                            }
                        });

                        var key = new ECDsaSecurityKey(ec);
                        key.KeyId = webKey.Kid;

                        keys.Add(key);
                    }
                    else
                    {
                        logger.LogDebug("Signing key with kid: {kid} currently not supported", webKey.Kid ?? "not set");
                    }
                }

                parameters.IssuerSigningKeys = keys;
            }

            return(handler.ValidateToken(identityToken, parameters));
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="AuthorizeClient"/> class.
 /// </summary>
 /// <param name="options">The options.</param>
 public AuthorizeClient(OidcClientOptions options)
 {
     _options = options;
     _logger  = options.LoggerFactory.CreateLogger <AuthorizeClient>();
     _crypto  = new CryptoHelper(options);
 }
 public CryptoHelper(OidcClientOptions options)
 {
     _options = options;
     _logger  = options.LoggerFactory.CreateLogger <CryptoHelper>();
 }
        /// <inheritdoc />
        public Task <IdentityTokenValidationResult> ValidateAsync(string identityToken, OidcClientOptions options, CancellationToken cancellationToken = default)
        {
            var parts = identityToken.Split('.');

            if (parts.Length != 3)
            {
                var error = new IdentityTokenValidationResult
                {
                    Error = "invalid_jwt"
                };

                return(Task.FromResult(error));
            }

            var payload = Encoding.UTF8.GetString((Base64Url.Decode(parts[1])));

            var values =
                JsonSerializer.Deserialize <Dictionary <string, JsonElement> >(payload);

            var claims = new List <Claim>();

            foreach (var element in values)
            {
                if (element.Value.ValueKind == JsonValueKind.Array)
                {
                    foreach (var item in element.Value.EnumerateArray())
                    {
                        claims.Add(new Claim(element.Key, item.ToString()));
                    }
                }
                else
                {
                    claims.Add(new Claim(element.Key, element.Value.ToString()));
                }
            }

            var result = new IdentityTokenValidationResult
            {
                SignatureAlgorithm = "none",
                User = new ClaimsPrincipal(new ClaimsIdentity(claims, "none", "name", "role"))
            };

            return(Task.FromResult(result));
        }
 public IdentityTokenValidator(OidcClientOptions options, Func <Task> refreshKeysAsync)
 {
     _options          = options;
     _logger           = options.LoggerFactory.CreateLogger <IdentityTokenValidator>();
     _refreshKeysAsync = refreshKeysAsync;
 }
예제 #11
0
 public OidcClient(OidcClientOptions options)
 {
     _authorizeClient = new AuthorizeClient(options);
     _options         = options;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="AuthorizeClient"/> class.
 /// </summary>
 /// <param name="options">The options.</param>
 public AuthorizeClient(OidcClientOptions options)
 {
     _options = options;
 }
 public ResponseValidator(OidcClientOptions options)
 {
     _options = options;
 }