poppinss / oauth-client

A framework agnostic package to implement "Login with" flow using OAuth compliant authorization servers
MIT License
23 stars 2 forks source link

Support for RFC8414 — OAuth 2 Authorization Server Metadata discovery #4

Open ThisIsMissEm opened 1 month ago

ThisIsMissEm commented 1 month ago

Currently with this package, one must manually specify the authorizeUrl (authorization_endpoint), accessTokenUrl (token_endpoint) and possible the user info URL (userinfo_endpoint). RFC 8414 allows for Authorization Servers to advertise all of those endpoints in a single well-known JSON file, that the client can fetch.

An example response is as follows:

{
      "issuer": "https://server.example.com",
      "authorization_endpoint": "https://server.example.com/authorize",
      "token_endpoint": "https://server.example.com/token",
      "token_endpoint_auth_methods_supported": ["client_secret_basic", "private_key_jwt"],
      "token_endpoint_auth_signing_alg_values_supported": ["RS256", "ES256"],
      "userinfo_endpoint": "https://server.example.com/userinfo",
      "jwks_uri": "https://server.example.com/jwks.json",
      "registration_endpoint": "https://server.example.com/register",
      "scopes_supported": ["openid", "profile", "email", "address", "phone", "offline_access"],
      "response_types_supported": ["code", "code token"],
      "service_documentation": "http://server.example.com/service_documentation.html",
      "ui_locales_supported": ["en-US", "en-GB", "en-CA", "fr-FR", "fr-CA"]
}

This is also part of OIDC Discovery, though there the URL is slightly different (/.well-known/openid-configuration or /issuer1/.well-known/openid-configuration instead of /.well-known/oauth-authorization-server).

This document advertises the scopes supported, which access grant flows are supported and a lot more.

For instance, here is Google's OpenID Configuration document for OIDC Discovery.


The way that I see this working in this package is that you specify an issuerUrl which is the path to service's discovery document, the package then gets this document by performing a fetch() call on that issuerUrl, and then extracts out the various URLs needed by other methods. This can happen once for the client given discovery document is generally fairly static.

That saves developers from hard coding endpoints, and also unlocks the ability to use features like the registration endpoint (for dynamic client registration), provide service documentation, fail fast on invalid scopes being provided, and support logging out from the authorization server (via the revocation_endpoint in OAuth or end_session_url in OIDC)

(My primary motivation for filing this issue is because I was looking at Adonis's Ally plugin which depends on this package, and thought "huh, this doesn't support ending the session on the OAuth / OIDC server.. that'd be good to have")

thetutlage commented 1 month ago

Okay, so there are a couple of things.

I think these URLs are hardcoded in the implementation of the drivers and if I get it right we do not make the end-user type them in the config.

So if we perform discovery, is the plan to remove these URLs from the drivers implementation and instead inject them via the config? If yes, any specific benefits it will bring?

ThisIsMissEm commented 1 month ago

This also means that you get the other configuration (scopes_supported & friends) from the IdP.

I do note that some existing providers don't support discovery though (which is a shame)