Пример #1
0
 public void IsNullOrEmpty_ReturnsTrueForNullValues()
 {
     // Arrange, act and assert
     Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter((bool?)null)));
     Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter((long?)null)));
     Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter((string?)null)));
     Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter((string[]?)null)));
 }
Пример #2
0
    public void IsNullOrEmpty_ReturnsTrueForEmptyValues()
    {
        // Arrange, act and assert
        Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(string.Empty)));
        Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(Array.Empty <string>())));

        Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(
                                                          JsonSerializer.Deserialize <JsonElement>("[]"))));
        Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(
                                                          JsonSerializer.Deserialize <JsonElement>("{}"))));
        Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(
                                                          JsonSerializer.Deserialize <JsonElement>(@"{""field"":""""}").GetProperty("field"))));
    }
Пример #3
0
    public void IsNullOrEmpty_ReturnsFalseForNonEmptyValues()
    {
        // Arrange, act and assert
        Assert.False(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(true)));
        Assert.False(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter((bool?)true)));
        Assert.False(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(42)));
        Assert.False(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter((long?)42)));
        Assert.False(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter("Fabrikam")));
        Assert.False(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(new[] { "Fabrikam" })));

        Assert.False(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(
                                                           JsonSerializer.Deserialize <JsonElement>(@"[""Fabrikam""]"))));
        Assert.False(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(
                                                           JsonSerializer.Deserialize <JsonElement>(@"{""field"":""Fabrikam""}"))));
        Assert.False(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(
                                                           JsonSerializer.Deserialize <JsonElement>(@"{""field"":""Fabrikam""}").GetProperty("field"))));
    }
    private HttpRequestMessage CreateRequestMessage(OpenIddictRequest request, HttpMethod method, Uri uri)
    {
        // Note: a dictionary is deliberately not used here to allow multiple parameters with the
        // same name to be specified. While initially not allowed by the core OAuth2 specification,
        // this is required for derived drafts like the OAuth2 token exchange specification.
        var parameters = new List <KeyValuePair <string?, string?> >();

        foreach (var parameter in request.GetParameters())
        {
            // If the parameter is null or empty, send an empty value.
            if (OpenIddictParameter.IsNullOrEmpty(parameter.Value))
            {
                parameters.Add(new KeyValuePair <string?, string?>(parameter.Key, string.Empty));

                continue;
            }

            var values = (string?[]?)parameter.Value;
            if (values is not {
                Length: > 0
            })
Пример #5
0
 public void IsNullOrEmpty_ReturnsTrueForUndefinedValues()
 {
     // Arrange, act and assert
     Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(default(JsonElement))));
 }
        private HttpRequestMessage CreateRequestMessage(OpenIddictRequest request, HttpMethod method, Uri uri)
        {
            // Note: a dictionary is deliberately not used here to allow multiple parameters with the
            // same name to be specified. While initially not allowed by the core OAuth2 specification,
            // this is required for derived drafts like the OAuth2 token exchange specification.
            var parameters = new List <KeyValuePair <string, string> >();

            foreach (var parameter in request.GetParameters())
            {
                // If the parameter is null or empty, send an empty value.
                if (OpenIddictParameter.IsNullOrEmpty(parameter.Value))
                {
                    parameters.Add(new KeyValuePair <string, string>(parameter.Key, string.Empty));

                    continue;
                }

                var values = (string[])parameter.Value;
                if (values == null || values.Length == 0)
                {
                    continue;
                }

                foreach (var value in values)
                {
                    parameters.Add(new KeyValuePair <string, string>(parameter.Key, value));
                }
            }

            if (method == HttpMethod.Get && parameters.Count != 0)
            {
                var builder = new StringBuilder();

                foreach (var parameter in parameters)
                {
                    if (builder.Length != 0)
                    {
                        builder.Append('&');
                    }

                    builder.Append(UrlEncoder.Default.Encode(parameter.Key));
                    builder.Append('=');
                    builder.Append(UrlEncoder.Default.Encode(parameter.Value));
                }

                if (!uri.IsAbsoluteUri)
                {
                    uri = new Uri(HttpClient.BaseAddress, uri);
                }

                uri = new UriBuilder(uri)
                {
                    Query = builder.ToString()
                }.Uri;
            }

            var message = new HttpRequestMessage(method, uri);

            if (method != HttpMethod.Get)
            {
                message.Content = new FormUrlEncodedContent(parameters);
            }

            return(message);
        }
            public async ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context)
            {
                if (context == null)
                {
                    throw new ArgumentNullException(nameof(context));
                }

                var parameters = await _cache.GetOrCreateAsync(
                    key : string.Concat("af84c073-c27c-49fd-a54f-584fd60320d3", "\x1e", context.Issuer?.AbsoluteUri),
                    factory : async entry =>
                {
                    entry.SetAbsoluteExpiration(TimeSpan.FromMinutes(30));
                    entry.SetPriority(CacheItemPriority.NeverRemove);

                    return(await GetTokenValidationParametersAsync());
                });

                context.TokenValidationParameters.ValidIssuer       = parameters.ValidIssuer;
                context.TokenValidationParameters.IssuerSigningKeys = parameters.IssuerSigningKeys;

                async ValueTask <TokenValidationParameters> GetTokenValidationParametersAsync()
                {
                    using var client = _factory.CreateClient(Clients.Discovery);
                    var response = await SendHttpRequestMessageAsync(client, context.Options.MetadataAddress);

                    // Ensure the JWKS endpoint URL is present and valid.
                    if (!response.TryGetParameter(Metadata.JwksUri, out var endpoint) || OpenIddictParameter.IsNullOrEmpty(endpoint))
                    {
                        throw new InvalidOperationException("A discovery response containing an empty JWKS endpoint URL was returned.");
                    }

                    if (!Uri.TryCreate((string)endpoint, UriKind.Absolute, out Uri uri))
                    {
                        throw new InvalidOperationException("A discovery response containing an invalid JWKS endpoint URL was returned.");
                    }

                    return(new TokenValidationParameters
                    {
                        ValidIssuer = (string)response[Metadata.Issuer],
                        IssuerSigningKeys = await GetSigningKeysAsync(client, uri).ToListAsync()
                    });
                }
Пример #8
0
            public async ValueTask HandleAsync([NotNull] ProcessAuthenticationContext context)
            {
                if (context == null)
                {
                    throw new ArgumentNullException(nameof(context));
                }

                var parameters = await _cache.GetOrCreateAsync(
                    key : string.Concat("af84c073-c27c-49fd-a54f-584fd60320d3", "\x1e", context.Issuer?.AbsoluteUri),
                    factory : async entry =>
                {
                    entry.SetAbsoluteExpiration(TimeSpan.FromMinutes(30));
                    entry.SetPriority(CacheItemPriority.NeverRemove);

                    return(await GetTokenValidationParametersAsync());
                });

                context.TokenValidationParameters.ValidIssuer       = parameters.ValidIssuer;
                context.TokenValidationParameters.IssuerSigningKeys = parameters.IssuerSigningKeys;

                async ValueTask <TokenValidationParameters> GetTokenValidationParametersAsync()
                {
                    using var client = _factory.CreateClient(Clients.Discovery);
                    var response = await SendHttpRequestMessageAsync(client, context.Options.MetadataAddress);

                    // Ensure the JWKS endpoint URL is present and valid.
                    if (!response.TryGetParameter(Metadata.JwksUri, out var endpoint) || OpenIddictParameter.IsNullOrEmpty(endpoint))
                    {
                        throw new InvalidOperationException("A discovery response containing an empty JWKS endpoint URL was returned.");
                    }

                    if (!Uri.TryCreate((string)endpoint, UriKind.Absolute, out Uri uri))
                    {
                        throw new InvalidOperationException("A discovery response containing an invalid JWKS endpoint URL was returned.");
                    }

                    return(new TokenValidationParameters
                    {
                        ValidIssuer = (string)response[Metadata.Issuer],
                        IssuerSigningKeys = await GetSigningKeysAsync(client, uri).ToListAsync()
                    });
                }

                async IAsyncEnumerable <SecurityKey> GetSigningKeysAsync(HttpClient client, Uri address)
                {
                    var response = await SendHttpRequestMessageAsync(client, address);

                    var keys = response[JsonWebKeySetParameterNames.Keys];

                    if (keys == null)
                    {
                        throw new InvalidOperationException("The OAuth 2.0/OpenID Connect cryptography didn't contain any JSON web key");
                    }

                    foreach (var payload in keys.Value.GetParameters())
                    {
                        var type = (string)payload.Value[JsonWebKeyParameterNames.Kty];
                        if (string.IsNullOrEmpty(type))
                        {
                            throw new InvalidOperationException("A JWKS response containing an invalid key was returned.");
                        }

                        var key = type switch
                        {
                            JsonWebAlgorithmsKeyTypes.RSA => new JsonWebKey
                            {
                                Kty = JsonWebAlgorithmsKeyTypes.RSA,
                                E   = (string)payload.Value[JsonWebKeyParameterNames.E],
                                N   = (string)payload.Value[JsonWebKeyParameterNames.N]
                            },

                            JsonWebAlgorithmsKeyTypes.EllipticCurve => new JsonWebKey
                            {
                                Kty = JsonWebAlgorithmsKeyTypes.EllipticCurve,
                                Crv = (string)payload.Value[JsonWebKeyParameterNames.Crv],
                                X   = (string)payload.Value[JsonWebKeyParameterNames.X],
                                Y   = (string)payload.Value[JsonWebKeyParameterNames.Y]
                            },

                            _ => throw new InvalidOperationException("A JWKS response containing an unsupported key was returned.")
                        };

                        key.KeyId   = (string)payload.Value[JsonWebKeyParameterNames.Kid];
                        key.X5t     = (string)payload.Value[JsonWebKeyParameterNames.X5t];
                        key.X5tS256 = (string)payload.Value[JsonWebKeyParameterNames.X5tS256];

                        if (payload.Value.TryGetParameter(JsonWebKeyParameterNames.X5c, out var chain))
                        {
                            foreach (var certificate in chain.GetParameters())
                            {
                                var value = (string)certificate.Value;
                                if (string.IsNullOrEmpty(value))
                                {
                                    throw new InvalidOperationException("A JWKS response containing an invalid key was returned.");
                                }

                                key.X5c.Add(value);
                            }
                        }

                        yield return(key);
                    }
                }