authts / oidc-client-ts

OpenID Connect (OIDC) and OAuth2 protocol support for browser-based JavaScript applications
https://authts.github.io/oidc-client-ts/
Apache License 2.0
1.26k stars 191 forks source link

Feature request for OAuth2.1 client authentication methods #1533

Open ch-lepp opened 4 weeks ago

ch-lepp commented 4 weeks ago

The OAuth2.1 spec does not require but strongly recommends asymmetric client authentication methods like "private_key_jwt" (source). In your documentation for your OidcMetadata interface you even hint towards the support of "private_key_jwt" with the attributes token_endpoint_auth_methods_supported and token_endpoint_auth_signing_alg_values_supported.

But for the attribute client_authentication within the OidcClientSettings interface you only support "client_secret_basic" and "client_secret_post" (as can bee seen in the code aswell).

Could you please add support for the OAuth2.1 recommended client auth methods?

dbfr3qs commented 2 weeks ago

The OAuth 2.1 spec is not even in RFC yet and is still under active development. I would suggest we wait until the RFC is ratified.

ch-lepp commented 2 weeks ago

I see your point and I would usually agree.

I just have the problem, that we use Keycloak in our setup as IDP. With version 24 Keycloak started support of OAuth2.1, which I'd like to use. Unfortunately, Keycloak requires all OAuth2.1-Clients to use either "private_key_jwt" or "x509 certificate".

And while OAuth2.1 is indeed still a draft, the "private_key_jwt" auth method itself is part of the OIDC core spec.

dbfr3qs commented 1 week ago

Okay, no problem - I see that you are correct that it is referenced in the OIDC core spec.

Given that oidc-client-ts supports public clients, it seems like a strange use case for web based applications. How would one securely supply the private key?

Say the key pair is registered when registering the client, the public key is stored at the IdP and the client is then expected to make use of the private key to sign the JWT to authenticate at the /token endpoint. Is that private key embedded into the application's javascript? The moment the private key enters the browser's execution environment, it's no longer a private key.

I see in the linked KeyCloak issue that you are using a confidential client. Can I ask how you are using oidc-client-ts in this case?

ch-lepp commented 1 week ago

Given that oidc-client-ts supports public clients, it seems like a strange use case for web based applications. How would one securely supply the private key?

The same problem already exists for the client secret, does it not? The client secret also needs to be securely provided to the client...

At the moment, oidc-client-ts offers to simply pass the client secret as an attribute of the OidcClientSettings. I think the same should be possible for the private key.

However, it is currently also possible to configure oidc-client-ts to use client-secret-post without providing the client secret as part of the OidcClientSettings. This way, the client secret can be provided in a more secure way, without adding it to the application's javascript.

E.g. the team I work for builds an app that uses a TS frontend in front of a java spring-boot backend. Our frontend sends the token request not to the IDP directly, but to our backend. Here the client secret is injected into the request before it is forwarded towards the IDP. We plan to use a similar approach for the signed JWT.

dbfr3qs commented 1 week ago

@pamapa what do you think? It's a no from me as this seems like a use case well outside of any of the specs or the current BCP.

As an aside we should not support client secret. That looks like a holdover from the original port (which is years out of date at this point).

Secrets that are statically included as part of an app distributed to multiple users should not be treated as confidential secrets, as one user may inspect their copy and learn the shared secret. For this reason, and those stated in Section 5.3.1 of [RFC6819], it is NOT RECOMMENDED for authorization servers to require client authentication of browser-based applications using a shared secret, as this serves no value beyond client identification which is already provided by the client_id parameter.

pamapa commented 16 hours ago

what do you think? It's a no from me as this seems like a use case well outside of any of the specs or the current BCP.

As an aside we should not support client secret. That looks like a holdover from the original port (which is years out of date at this point).

I agree that it is very very bad to use client secrets in applications exposed to users (e.g. web applications or smartphone applications). But there exists also applications using nodejs and running servers (back-end application). They do not expose any code to users. for those it should be safe to use client secrets...

dbfr3qs commented 10 hours ago

what do you think? It's a no from me as this seems like a use case well outside of any of the specs or the current BCP. As an aside we should not support client secret. That looks like a holdover from the original port (which is years out of date at this point).

I agree that it is very very bad to use client secrets in applications exposed to users (e.g. web applications or smartphone applications). But there exists also applications using nodejs and running servers (back-end application). They do not expose any code to users. for those it should be safe to use client secrets...

Yes, but in that I case I would use a library like opened-client which is designed for that use case - not oidc-client-ts. Are you saying we can support this use case in oidc-client-ts?