Search code examples
oauth-2.0

OAuth 2.0: why is the access token or temporary code placed in the in the URL fragment (after the #) instead of in the query string?


I am learning OAuth 2.0.

In both code flow and implicit flow (response_type = code or token). The temporary code or access_token is placed in the URL fragment (after the #) instead of in the query string.

According to this doc: https://developer.okta.com/blog/2018/05/24/what-is-the-oauth2-implicit-grant-type:

If the user approves the request, the authorization server will redirect the browser back
 to the redirect_uri specified by the application, adding a token and state to the fragment 
part of the URL.

For example, the user will be redirected back to a URL such as: 

https://example-app.com/redirect
  #access_token=g0ZGZmNj4mOWIjNTk2Pw1Tk4ZTYyZGI3
  &token_type=Bearer
  &expires_in=600
  &state=xcoVv98y2kd44vuqwye3kcq

Note the two major differences between this and the Authorization Code flow: the access token is returned 
instead of the temporary code, and both values are returned in the URL fragment (after the #) instead
 of in the query string. By doing this, the server ensures that the app will be able to access the value 
from the URL, but the browser won’t send the access token in the HTTP request back to the server.

What exactly does it mean by

the server ensures that the app will be able to access the value from the URL, but the browser won’t send the access token in the HTTP request back to the server.

?

Of course the code/ access_token value is accessible from the URL.

The Auth server builds up the url and put it in location header of the HTTP response, which is sent back to the user's web browser. The web browser then take values from the response, and send new http requests to the application instead of the Auth server. So, of course the user's web browser is not sending HTTP request back to the server.

It has nothing to do with where the access token is placed in the response (from Auth server back to the user's web browser). The web browser simply starts talking to the application again instead of the Auth server.

This explanation just does not make much sense to me.


Solution

  • The code flow returns an authorization code to the browser in the query string. You then make a POST request to swap the code for tokens.

    https://www.example.com?code=xxx&state=yyy
    

    Implicit flow is now deprecated since it can reveal tokens in the browser history or server logs. It dates back to when browsers did not have CORS capabilities to make cross orign POST requests to the Authorization Server.

    Data in client side hash fragments does not get sent to servers and the implicit flow used this as a partial mitigation for sensitive data. Eg the zzzz below does not get sent to the web server if you type this in a browser.

    https://www.example.com#zzzz
    

    If you are new to OAuth and OpenID Connect, start with code flow + PKCE, and understand these messages.

    SWAPPING THE CODE FOR TOKENS

    This is often done via a back end component that completes the flow, so that a client secret can be attached (a browser cannot keep secrets). This back end component can then do either of these:

    • Return access tokens to the browser
    • Issue secure cookies to the browser

    Once done, the front end has a credential with which it can call the main back end (eg APIs), so that the back end knows the user identity.

    CODE EXAMPLE

    In 2021 the cookie option is considered more secure, but it also requires a more complex flow. All of the complexity involved originates from the browser being a hostile place to execute code - there are lots of security threats there. Here is some example code that uses cookies: