9

So I've been looking at setting up OAuth 2.0 for a Cordova mobile app using Microsofts cordova-plugin-ms-adal plugin (which uses the native libs) against a custom API using Azure AD. This all works well but I'm a bit confused with the use of the secret (or more specifically its absence).

In many articles on the web they state that when using the Authorization Code Grant and requesting a token, you include the secret. And that this grant type is ideal for use when you can securely store the secret e.g. on a server.

However the plugin does not require that a secret is specified in the app (and rightly so) but it still uses the Authorization Code Grant to authenticate. Also I can manually call

https://login.windows.net/common/oauth2/authorize?resource=http://***.onmicrosoft.com/***API&client_id=***&response_type=code&redirect_uri=http://***.onmicrosoft.com/***App

in my browser, login, get the code and then POST to https://login.windows.net/common/oauth2/token with

grant_type: authorization_code
client_id: ***
code: ***
redirect_uri: http://***.onmicrosoft.com/***App
resource: http://***.onmicrosoft.com/***API

and it works, so I get back a valid JWT, without having to send a secret.

Why!? Is this less secure? (I also noticed that the OAuth 2.0 spec section 4.1.3 does not state that the secret is required for grant type Authorization Code!?)

What are the implications of using a grant type of authorization_code without a secret / basic auth header?

Community
  • 1
  • 1
Ross
  • 1,425
  • 1
  • 19
  • 38
  • Can you tell me how did you get the code in the browser login and did you make a POST using Javascript or any server side Language. I am facing this issue and need your help!!!! – Sourav Das Oct 19 '16 at 19:15
  • @SouravDas So that I could get a better understanding I was calling the endpoints manually. Once you call the first URL in your browser and login it redirects to the redirect_uri you have configured with a ?code= param. Use this value when you POST to the token endpoint - I used https://www.getpostman.com for testing this. In my actual code I have the cordova-plugin-ms-adal plugin setup which handles this for me! – Ross Oct 20 '16 at 09:13
  • Thanks for the reply. We use ADFS not AZAD so, i guess i have to write the whole thing!! – Sourav Das Oct 20 '16 at 14:10

3 Answers3

12

Using the Authorization Code grant with a so-called confidential client (a client that has a client secret) is more secure than using a public Client indeed.

That is because the exchange of the authorization code itself happens as URL parameter in the front-channel i.e. through the browser and as such is relatively vulnerable to attacks like cross-scripting, click-jacking, network/DNS manipulation etc. That means that it is possible for a dedicated attacker to steal the authorization code from a user in certain circumstances (sloppy user, attacker network control, sloppy redirect URI matching in the server implementation, etc.).

To exchange the authorization code for an Access Token, a confidential Client would have to present the client secret on an HTTPs protected call alongside of the authorization code, whereas a public Client doesn't have any means of making sure that it is really the designated Client.

This means that it is relatively easy for an attacker to mimic a public Client since that requires only non-secret information (he can grab the client_id and the redirect_uri from his own browser) and the authorization code that he can grab through an attack as described above.

Though grabbing the authorization code for a confidential Client works in the same way, the attacker cannot use it and exchange it for an Access Token because in order to do so he needs a client secret which is typically much harder to obtain for the attacker. The secret is usually stored on the server in backend storage and communicated only over a secure HTTPs channel so it doesn't leak.

Hans Z.
  • 50,496
  • 12
  • 102
  • 115
5

The implication of using grant_type=authorization_code (or any other flow) with a public client (one that does not have a secret or authenticate in any other way) is that the access token granted does not represent an authorization of the client to directly access the resource, it represents an authorization for the client to access the resource on behalf of the user.

This is why you'll notice in Azure AD that when you register a native client app (a public client) you can only configure it to have delegated permissions to a resource, and not app-only permissions.

Philippe Signoret
  • 13,299
  • 1
  • 40
  • 58
1

without having to send a secret.

Not true. In the link you posted the request includes also:

Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

Maybe you didn't notice it. This shows the client_secret being transmitted in an encoded form, using HTTP Basic Authentication.

It's up to the server to decide how the client authenticates (if necessary). From the specification :

If the client type is confidential or the client was issued client credentials (or assigned other authentication requirements), the client MUST authenticate with the authorization server as described in Section 3.2.1.

Sec 3.2.1 directs to section 2.3 (seriously), which says:

Clients in possession of a client password MAY use the HTTP Basic authentication scheme as defined in [RFC2617] to authenticate with the authorization server.

client password is aka client secret.

So the secret is being transmitted.

Community
  • 1
  • 1
Tomas Mano
  • 29
  • 5
  • 1
    Thanks Tomas. I'll admit that I didn't notice that in the spec example! I guess my question is: what are the implications of using a grant type of authorization_code without a secret / basic auth header? (I've updated my question to reflect this.) – Ross Sep 02 '16 at 13:46