I'm learning OAuth 2.0. When using authorization code flow, it's enough to pass client ID. Does it mean that, in theory, an attacker can generate multiple authorization codes easily?
What was the reason why the consent screen doesn't use client secret? It's secure, as authorization server should deliver HTTPS connection.
Is it only for simplicity, to allow linking on client-side, like this?
Login with Koala Auth
No, according to RFC-6749 section 1.3.1, the user is authenticated by the Authorization Server before an authorization code is given back. Therefore, the client ID is not the only piece of data the is needed to get an authorization code.
This is not because the resource owner redirects the user-agent to the authorization server that this authorization server will give back an authorization code: the user-agent must complete an authentication step with a valid user, before the authorization code is given back to the resource owner.
Related
I tried to login with two separate website, both using "login with Google". Intercepted the auth code from the 1st site, and exchange it with the auto code to the 2nd site. Neither site will let me login. I remember in RFC6749 it is not specified that the auth code to be bound with any identity, is it implemented so to increase security?
This is indeed part of OAuth2.0 security:
Exchange the Authorization Code for an Access Token
We’re about ready to wrap up the flow. Now that the application has
the authorization code, it can use that to get an access token.
The application makes a POST request to the service’s token endpoint
with the following parameters:
grant_type=authorization_code - This tells the token endpoint that the
application is using the Authorization Code grant type.
code - The
application includes the authorization code it was given in the
redirect.
redirect_uri - The same redirect URI that was used when
requesting the code. Some APIs don’t require this parameter, so you’ll
need to double check the documentation of the particular API you’re
accessing.
client_id - The application’s client ID.
client_secret -
The application’s client secret. This ensures that the request to get
the access token is made only from the application, and not from a
potential attacker that may have intercepted the authorization code.
from https://developer.okta.com/blog/2018/04/10/oauth-authorization-code-grant-type#exchange-the-authorization-code-for-an-access-token
Short answer : Authorization code is bound to the client it was issued
This is strictly enforced by the RFC6749 and stated in 4.1.3. Access Token Request section. Also, it is one of many checkes authorization server perform to validate a token request. Specification has following stated,
The authorization server MUST:
o ensure that the authorization code was issued to the authenticated
confidential client, or if the client is public, ensure that the code
was issued to "client_id" in the request
So when authorization server will cross check authorization code against client id or client credentials depending on client type.
Furthermore, authorization code is a temporary secret which must not be exposed to other parties. This is highlighted in security consideration's 10.5. Authorization Codes section.
I am a beginner to OAuth so my question might sound naive. I found this picture online describing how OAuth works.
Let's say the client already did the authorization before, which means we already know which authorization the clients get.
So, for the second time when the client request the authorization, I am not sure why can't we request the authorization from the client and return the protected resources from the server back to the client? So basically we skip steps 2, 3, 4 and 5, and we only keep steps 1 and 6.
What are you looking at there is the "Authorization Code Grant". This means you have an authentication service that is capable of serving back a login form to the user, authenticates them and then issues a grant. This grant is then turned into an access token via another call.
If you want to do application level authentication then use the Client Credential Grant
This means that you have a ClientID and ClientSecret which identify an application, not a user. You issue a request with those and you get back a token you can use to access a protected resource.
An example is here: https://eidand.com/2015/03/28/authorization-system-with-owin-web-api-json-web-tokens/
If you want to use user credentials for authentication then you can use the Resource Owner Password Credential Grant for example.
So, it all depends on what you are looking for.
Authorization code flow - User logs in from client app, authorization server returns an authorization code to the app. The app then exchanges the authorization code for access token.So, I want to know what is the content that authorization server sends as authorization code?I mean what code or signature does a authorization code contains?
Authorization Code in oAuth is explained in the RFC for oAuth, in section 1.3.1 called Authorization Code. See:
https://www.rfc-editor.org/rfc/rfc6749#section-1.3.1
The authorization code is obtained by using an authorization server as
an intermediary between the client and resource owner. Instead of
requesting authorization directly from the resource owner, the client
directs the resource owner to an authorization server (via its
user-agent as defined in [RFC2616]), which in turn directs the
resource owner back to the client with the authorization code.
Before directing the resource owner back to the client with the
authorization code, the authorization server authenticates the
resource owner and obtains authorization. Because the resource owner
only authenticates with the authorization server, the resource owner's
credentials are never shared with the client.
The authorization code provides a few important security benefits,
such as the ability to authenticate the client, as well as the
transmission of the access token directly to the client without
passing it through the resource owner's user-agent and potentially
exposing it to others, including the resource owner.
It is explained in more details with block diagrams in section 4.1 Authorization Code Grant, and in section 10.5 Authorization Codes. See:
https://www.rfc-editor.org/rfc/rfc6749#section-4.1
https://www.rfc-editor.org/rfc/rfc6749#section-10.5
Some relevant quotes from the documentation referenced above:
The transmission of authorization codes SHOULD be made over a secure
channel, and the client SHOULD require the use of TLS with its
redirection URI if the URI identifies a network resource. Since
authorization codes are transmitted via user-agent redirections, they
could potentially be disclosed through user-agent history and HTTP
referrer headers.
Authorization codes operate as plaintext bearer credentials, used to
verify that the resource owner who granted authorization at the
authorization server is the same resource owner returning to the
client to complete the process. Therefore, if the client relies on
the authorization code for its own resource owner authentication, the
client redirection endpoint MUST require the use of TLS.
Authorization codes MUST be short lived and single-use. If the
authorization server observes multiple attempts to exchange an
authorization code for an access token, the authorization server
SHOULD attempt to revoke all access tokens already granted based on
the compromised authorization code.
If the client can be authenticated, the authorization servers MUST
authenticate the client and ensure that the authorization code was
issued to the same client.
See the rest of RFC 6749 for more details:
https://www.rfc-editor.org/rfc/rfc6749
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?
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.
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.
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.
When I first heard of OAuth was in ASP.NET Web API applications and I've used it as means of authorizing users to access resources on a RESTful API. By the time I felt I was using it right, but right now I think I got the idea wrong and this is the subject of this question.
At the time, I used OAuth in the following way: on the API there was a token endpoint to issue tokens. I created a login page in a SPA and posted the username and password to the token endpoint with a grant type password and the token that came back I started sending with each request.
When the request had the Authorization: Bearer [token] header with a token issued with some username on the login page I understood the request was being done "with the user logged in" and so I could authorize access to resources.
Studying OAuth deeper my conclusion is that my usage of OAuth was completely mistaken.
My understanding now is that OAuth is just for authorizing applications and not users. In that case when we make a request with the Authorization: Bearer [token] header we are saying identifiying to the resource server that the client making the request has been authorized to access the resource, but we are not saying anything about the user?
In that case, with OAuth we just can say what resources client applications can access but we have no information to decide whether the user is allowed or not to the resource? Because of that my initial usage is truly wrong right?
OAuth 2.0 can be used for authorizing a client (an application) to call an API. This authorization is done via an authorization grant.
The grant is given by the resource owner in the case of authorization code, implicit and resource owner password grant through authentication of the user with the authorization server and clicking accept on a consent screen.
The first two grant flows are interactive and require an agent that understands HTTP (redirection) responses.
Most authorization servers also support the client credentials grant. In this case, there's no user involved and a pre-registered client (application) uses its own client-id and secret to authenticate with the authorization server.
Which grant flow to use depends on the type of client you use and who owns the resource the client needs to access. I describe the differences in my answer here.