9

Sources such as this Okta sponsored site (see "Per-Request Customization" section) mention that the redirect_uri parameter of a autorization request SHOULD NEVER have a dynamic query part (ex: for session matching uses).

Quote:

The server should reject any authorization requests with redirect URLs that are not an exact match of a registered URL.

Our OAuth AZ provider is BIG-IP F5. We are setting it up, and they seem to comply with the above view.

Our client is a web application built elsewhere, and they seem to not follow the above rule. Here is a complete representation of the Authorization Endpoint (redacted): https://ourownF5host.ca/f5-oauth2/v1/authorize?client_id=theIDofOurClient&redirect_uri=https%3A%2F%2FourClientAppHostname%2FClientRessource%2FRessource%3FSessionId%3D76eab448-52d1-4adb-8eba-e9ec1b9432a3&state=2HY-MLB0ST34wQUPCyHM-A&scope=RessourceData&response_type=code

They use a redirect_uri with a format similar to (I don't urlencode here, for simplicity's sake) : redirect_uri=https://ourClientAppHostname/ClientRessource/Ressource?SessionId=SOMELONGSESSIONID, with the SOMELONGSESSIONID value being DIFFERENT for each call.

We dug DEEP into RFC6749 (OAuth2), and found this in section 3.1.2.2:

The authorization server SHOULD require the client to provide the
complete redirection URI (the client MAY use the "state" request
parameter to achieve per-request customization). If requiring the
registration of the complete redirection URI is not possible, the
authorization server SHOULD require the registration of the URI
scheme, authority, and path (allowing the client to dynamically vary
only the query component of the redirection URI when requesting
authorization).

What I understand, and would like to validate here, is that the first source, Okta and F5 accept ONLY the first part of the rule above, and require the redirection uri to be COMPLETELY registered without any dynamic part.

Am I right to affirm that they (Okta and F5) DO NOT comply with the second part of the excerpt, citing that they should "allow(ing) the client to dynamically vary only the query component of the redirection URI when requesting authorization" ?

OR, is there any kind of official correction/evolution of the RFC6749, that warrants both companies design position ?

GhislainCote
  • 1,502
  • 11
  • 18
  • Can you please post the full authorization request URI that is generated by your client (the one issued to your AS authorization endpoint, that contains the client_id, redirect_uri, scope and response_type). You can redact those parameter values if needed. – Guillaume Apr 08 '19 at 16:33
  • @Guillaume I tried to update the question as best I could. Note that I now understand that the "state" parameter was correctly removed from the "redirect_uri" query parameter in the Authorization Endpoint. But my original question still stands for the "SessionId" parameter (not present in the original phrasing, I was confused am mixed them up). Please update your answer accordingly... – GhislainCote Apr 08 '19 at 17:15
  • 1
    My answer still stands. – Guillaume Apr 08 '19 at 17:25
  • That is what I figured... but since I changed the question a bit, I wanted to make sure. I will be awarding the bounty soon. (I am in discussions with other stakeholders) – GhislainCote Apr 08 '19 at 17:28

2 Answers2

16

TL;DR:

No, the redirect uri must be static for security reasons. If the client needs to keep a state between the authorization request and its asynchronous response, use the OAuth 2.0 state parameter.

Long version :

RFC6749 (the initial OAuth 2.0 specification) has been published in 2012 and OAuth security landscape has evolved a lot since then.

RFC6819, an OAuth 2.0 security review from 2013 already mentioned that refusing dynamically crafted redirect uris was a good way to protect against XSS and client impersonation attacks.

OpenID Connect, from 2014, a commonly used extension of OAuth 2.0 with authentication capabilities, already takes that recommendation into account and mandates exact string matching for all redirect uris.

The current draft recommendation for OAuth 2.0 Best Security Practice confirms that by enforcing redirect_uris preregistration and mandating the use simple string comparison by the AS when validating the redirect_uri passed in the request. So a dynamic redirect_uri must not be used.

Your client definitely makes a wrong move by using the redirect_uri as a "state keeper" between the Authorization request and response, by using a dynamically crafted SessionID attribute inside the redirect_uri. OAuth2.0 has a dedicated authorization request parameter for that purpose, which is "state". The client should use it. The AS will append that state in the parameters of the redirect_uri when it issues the response, so the client will be able to find back this state inside the response.

The proper authorization request would be:

https://youras/authorize?client_id=your_client_id&response_type=code&state=SOMELONGSTATE&redirect_uri=https%3A%2F%2Fsomehost%2Fauthcallback

The response will look like: https://somehost/authcallback?state=SOMELONGSTATE&code=anazcode

This way the redirect_uri is static, so a simple string comparison is enough to validate that uri on AS side. Any algorithm more complex than simple string comparison would be subject to security flaws.

Community
  • 1
  • 1
Guillaume
  • 5,497
  • 3
  • 24
  • 42
  • Hi ! Look at the url in the question... my client seem to be using "state". So my OAuth2 AZ vendor should support this query parameter to be dynamic, in your opinion ? – GhislainCote Apr 08 '19 at 16:25
  • From what I understand from your question, the `state` is part of the redirect_uri, which is itself a parameter of the authorization request. That `state` is supposed to be a parameter of the authorization request, and the `redirect_uri` must be a static that is preregistered for your specific client on the authorization server. – Guillaume Apr 08 '19 at 16:28
  • I tried to clarify the proper use of the `state` parameter in my answer. – Guillaume Apr 08 '19 at 16:44
  • 1
    Update : the client application used a .Net library that included the "SessionId" in the "redirect_uri" as an option. They (que client devs) changed the option and are now relying strictly on the "state" query parameter inside the "Authorization Endpoint Request" itself (but not inside "redirect_uri". Thanks @Guillaume ! – GhislainCote Apr 10 '19 at 22:06
2

It appears there's two things mixed up here: the URL you refer to:

 https://somehost/authcallback?state=SOMELONGSTATE&scope=someobjecttype&response_type=code

suggests that you mixed up the Redirect URI (aka. callback URL, as suggested by the pathname in the URL) of the Client with the Authorization Endpoint of the Authorization Server.

Only the Authorization Endpoint would take parameters as suggested and may contain e.g. a dynamic state value. The Redirect URI of the Client would not contain e.g. response type.

A redirect_uri parameter can be added to the the authorization request, which would then have to be matched in the way that you described. After confirming the match, the Authorization Server will redirect back to the Redirect URI, adding the code and state parameters.

Update (after the question changed):

OAuth 2.0 RFC6749 allows a dynamic (SessionId) parameter though it is not considered best practice. If however your client is an OpenID Connect Client, this is not allowed since the OpenID Connect spec (a "profile" of OAuth 2.0) locks down the Redirect URI matching to "exact", in which case you'd have to configure all possible SessionIds.

Hans Z.
  • 50,496
  • 12
  • 102
  • 115
  • You are right, I mixed "SessionId" (inside "redirect_uri") and "state"... My question still stands for "SessionId" (could/should it be dynamic) ? – GhislainCote Apr 08 '19 at 17:17