OAuth 2.0 Authorization Code Grant without secret
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.
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.