13
votes

In oauth you make a request using you client id/secret to get an authorization code. Then you make a second request to exchange the authorization code for access token. My question is:

Why is this two step process required instead of getting access token in the first place? How does it make the whole process more secure? Or is there another reason.

I'm talking about server side app (like php for example) requesting authorization from a remote server, not javascript.

3

3 Answers

7
votes

It's possible to do it with a single request - it's called the implicit flow then. There is a single request with response_type set to token or id_token token.

The general idea of using access code (authorization flow) instead of directly returning the tokens is to hide them from the end user. The second request is done usually by the backend server instead of a browser.

You can find more details here: https://auth0.com/docs/api-auth/which-oauth-flow-to-use

Note: for complete answer read the comments.

1
votes

In oauth you make a request using you client id/secret to get an authorization code.

Authorization code request does not contain the client secret. It only contain the client ID and redirect url, which enable authorization server to validate the request to originate from a known client.

What is this two step process required instead of getting access token in the first place? How does it make the whole process more secure? Or is there another reason.

If we forget about implicit flow, which involves retrieving access token from first call, I would say it is to improve security.

When authorization code flow is used, you use a user agent (browser) to initiate the flow. This means, the user agent will redirect end user to authorization server for authentication (username password obtaining and validating end user). If end user validation succeed, authorization server sends the authorization code. This is a temporary secret, which is bound to original authorization code request.

Now client use the authorization code and directly contact authorization server to obtain access (and other) tokens. This second step occur outside the user agent.

If the client is a confidential client, a client which has a client ID as well as a client secret, this second call will require to produce this client secret. So it internally contain a client validation process. From authorization server perspective, token request will be rejected if client authentication failed. This gives protection for authorization code stealing.

Also, with the second step, we avoid access token exposure to third party. For example, in implicit flow, access token is sent as URL fragments through user agent. If user agent is compromised (ex:- Manipulated by some malicious code) this access token can be extracted.

What about public clients ? That means clients which does not get a client secret due to their nature (ex:- Clients which cannot protect the secret by storing)

Public clients use PKCE. It is a must to use this to avoid authorization code stealing. So in the token request (second call), client will directly send code verifier. User agent cannot obtain code verifier in the first request since it was hashed (code challenge). So token request now contains a secret that only known by client and authorization server.

If you compare both scenarios (public and confidential clients), you can see how the second call adds an extra layer of security.

0
votes

More secure... Or less? Depends on how it's applied.

Have a look at: https://auth0.com/docs/api-auth/which-oauth-flow-to-use

You'll notice that the auth code flow is used when it's used on the server side. Also do notice that when an auth code is requested the response url has a query string with a question mark: https://example-app.com/redirect?code=g0ZGZmNjVmOWI&state=dkZmYxMzE2

When using a spa, you'll be using the implic flow. Notice that the accesstoken is sent through an anchor(#) in the url https://example-app.com/redirect#access_token=MyMzFjNTk2NTk4ZTYyZGI3

An anchor value will never be sent to the server. It will only be available to the client in the spa. The server will never be able to see the access token.

When a server app gets a redirect it must be able to read it. It can, because the url has a question mark instead of a #. If it would send the token directly, the client could see the access token in his browser history, or through fiddler.