ramosbugs / openidconnect-rs

OpenID Connect Library for Rust
MIT License
404 stars 100 forks source link

Error while parsing response from oidc discovery #102

Closed holly-hacker closed 1 year ago

holly-hacker commented 1 year ago

I am trying to integrate OpenID Connect into my application and used a mock OICD server to develop against. Everything worked fine, but when I switched to my production identity server, the call to discovery failed with the following message:

Failed to parse server response

Caused by:
    0: .: missing field `keys` at line 1 column 2
    1: missing field `keys` at line 1 column 2

The strange part is that my mock server does not seem to have this keys field and it still works. I don't know if this is a misconfiguration on my end, or a bug in openidconnect-rs.

Repro info

In my rust app I use openidconnect 2.5.0, but 3.0.0-alpha.1 shows the same issue.

For the mock server, I use mock-oauth2-server v0.5.7, and the http://localhost:8090/default/.well-known/openid-configuration endpoint returns the following json:

json response

```json { "issuer" : "http://localhost:8090/default", "authorization_endpoint" : "http://localhost:8090/default/authorize", "end_session_endpoint" : "http://localhost:8090/default/endsession", "token_endpoint" : "http://localhost:8090/default/token", "userinfo_endpoint" : "http://localhost:8090/default/userinfo", "jwks_uri" : "http://localhost:8090/default/jwks", "introspection_endpoint" : "http://localhost:8090/default/introspect", "response_types_supported" : [ "query", "fragment", "form_post" ], "subject_types_supported" : [ "public" ], "id_token_signing_alg_values_supported" : [ "ES256", "ES384", "RS256", "RS384", "RS512", "PS256", "PS384", "PS512" ] } ```

For my production server, I use Authentik 2023.2.2, and my endpoint https://auth.variant9.dev/application/o/test-openid-explicit-app/.well-known/openid-configuration returns the following json:

json response

```json { "issuer": "https://auth.variant9.dev/application/o/test-openid-explicit-app/", "authorization_endpoint": "https://auth.variant9.dev/application/o/authorize/", "token_endpoint": "https://auth.variant9.dev/application/o/token/", "userinfo_endpoint": "https://auth.variant9.dev/application/o/userinfo/", "end_session_endpoint": "https://auth.variant9.dev/application/o/test-openid-explicit-app/end-session/", "introspection_endpoint": "https://auth.variant9.dev/application/o/introspect/", "revocation_endpoint": "https://auth.variant9.dev/application/o/revoke/", "device_authorization_endpoint": "https://auth.variant9.dev/application/o/device/", "response_types_supported": [ "code", "id_token", "id_token token", "code token", "code id_token", "code id_token token" ], "response_modes_supported": [ "query", "fragment", "form_post" ], "jwks_uri": "https://auth.variant9.dev/application/o/test-openid-explicit-app/jwks/", "grant_types_supported": [ "authorization_code", "refresh_token", "implicit", "client_credentials", "password", "urn:ietf:params:oauth:grant-type:device_code" ], "id_token_signing_alg_values_supported": [ "HS256" ], "subject_types_supported": [ "public" ], "token_endpoint_auth_methods_supported": [ "client_secret_post", "client_secret_basic" ], "acr_values_supported": [ "goauthentik.io/providers/oauth2/default" ], "scopes_supported": [ "openid", "email", "profile" ], "request_parameter_supported": false, "claims_supported": [ "sub", "iss", "aud", "exp", "iat", "auth_time", "acr", "amr", "nonce", "email", "email_verified", "name", "given_name", "family_name", "preferred_username", "nickname", "groups" ], "claims_parameter_supported": false } ```

I am trying to get the provider metadata using the following code, which is the code that fails:

let provider_metadata = CoreProviderMetadata::discover_async(
    self.issuer_url.clone(),
    openidconnect::reqwest::async_http_client,
)
.await?;

I have double-checked that the issuer urls are the following:

holly-hacker commented 1 year ago

The following diff fixes the issue:

diff --git a/src/types.rs b/src/types.rs
index 71abb9c..acda96a 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -721,7 +721,7 @@ where
 {
     // FIXME: write a test that ensures duplicate object member names cause an error
     // (see https://tools.ietf.org/html/rfc7517#section-5)
-    #[serde(bound = "K: JsonWebKey<JS, JT, JU>")]
+    #[serde(bound = "K: JsonWebKey<JS, JT, JU>", default = "Vec::new")]
     // Ignores invalid keys rather than failing. That way, clients can function using the keys that
     // they do understand, which is fine if they only ever get JWTs signed with those keys.
     #[serde_as(as = "VecSkipError<_>")]

I will create a PR with this change.

ramosbugs commented 1 year ago

In this case, the issue is the OIDC provider returning an invalid JWK set that doesn't adhere to the spec.