thephpleague / oauth2-server

A spec compliant, secure by default PHP OAuth 2.0 Server
https://oauth2.thephpleague.com
MIT License
6.49k stars 1.12k forks source link

Make `redirect_uri` dynamic or support wildcards (for authorization code grant) #1271

Closed BurningDog closed 2 years ago

BurningDog commented 2 years ago

The docs at https://oauth2.thephpleague.com/authorization-server/auth-code-grant/ say:

redirect_uri with the client redirect URI. This parameter is optional, but if not send the user will be redirected to a pre-registered redirect URI.

This seems to imply that redirect_uri could be dynamically set by the requesting client. However, this is not the case - only pre-registered redirect_uris are allowed - see RedirectUriValidator::matchExactUri() - and note that validateRedirectUri() is not implemented by AuthCodeGrant.

Feature request

  1. Implement validateRedirectUri() in AuthCodeGrant and allow for a redirect_uri which is specified in the incoming request, or
  2. Add wildcard matching to the RedirectUriValidator

I would prefer 1. More context follows for my use-case.

BurningDog commented 2 years ago

My use case

The websites I'm authenticating with OAuth make API calls to my business API - everything is on different domains. I don't want to store the OAuth JWT in localStorage, but rather httpOnly secure cookies. That cookie then must be set by the API - which makes it part of the OAuth flow (from a user perspective) and the user must be automatically redirected back to their starting point once done.

During the OAuth authorization code grant workflow, the user needs to be sent back from the connecting API to their starting point - on the source website. I need to know what this starting point is, either by putting it into a session on the API, or (which is much easier), having a source parameter in the redirect_uri which will match any value.

Step by step explanation

I would like to connect multiple resource websites to my OAuth server. Each of these websites are JavaScript apps which make API calls to a backend which needs to load up the User object from the OAuth server. So instead of the authorization code grant workflow being:

it is:

In the first flow, the OAuth client is the website; in the second, it is the backend API.

In the first flow, the url in the redirect to website step is https://example.com/redirected, which is the url I've registered when creating the OAuth client.

However, in the second flow, I would like redirect to a specially crafted url on backend API to look like https://my-business-api.com/redirected?source=https://example.com/dashboard (or https://my-business-api.com/redirected?source=example-website as I can then get the value of example-website from the database).

Proposal 1: implement validateRedirectUri() in AuthCodeGrant

This would then match the docs and would be my preferred approach.

I'm happy to PR this, but wanted to check this approach would be ok.

Proposal 2: wildcard matching

The redirect_uri value of https://my-business-api.com/redirected?source={*} would then match https://my-business-api.com/redirected?source=https://another-website.com

I'm not sure how happy bash would be with this command. I'm using zsh on Mac, and

console league:oauth2-server:update-client EGAPI --add-redirect-uri=https://my-business-api.com/redirected?source={*}

got auto-changed to

console league:oauth2-server:update-client EGAPI --add-redirect-uri=https://my-business-api.com/redirected\?source\=\{\*\}

This seems a bit harder to implement - regex matching, and messing around with curly brackets in shells.

Sephster commented 2 years ago

Sorry for the confusion here @BurningDog. The client can pre-register multiple return URLs and can specify which one they want to use when issuing a request or can leave the parameter blank and we will use either the first redirect uri registered or the only redirect uri registered.

See this code for where we do this https://github.com/thephpleague/oauth2-server/blob/19dc5e47c465bc9f1804859660b7efe456a40713/src/Grant/AuthCodeGrant.php#L399-L411

The OAuth 2 spec dictates that we must have exact matching URIs for redirects and as far as I can recall, these shouldn't be dynamically set ever. Sorry again for any confusion caused around this.

I will mark this issue as closed but feel free to come back with any further comments and I will reopen this if i've made a mistake anywhere. Thanks

ajgarlag commented 2 years ago

@BurningDog Have you evaluated using the state param to convey your dynamic data?

See https://www.oauth.com/oauth2-servers/redirect-uris/redirect-uri-registration/#per-request