From section 1.3.1:
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.
Since authorization code allows for authenticating the client (as an additional security measure), why isn't it called authentication code?
It is primarily called authorization code because OAuth 2.0 is about authorization and not about (user) authentication.
It doesn't actually authenticate the client in the traditional "static" or "pre-established" sense. It just makes sure that the client requesting the token is the same as the that the authorization response was sent to.
In fact there's a separate set of client authentication options that can be applied to actually authenticate the client to the token endpoint in the classic sense.
Related
I am working on the ASP.NET MVC 5 web application. It has only one layer which contains views as well as business logic/operations. Business logic is logically separated from UI but it is not behind a separate web service/API layer.
Now when I use OIDC and OAuth2.0 for my application, there is no separate Resource Server, so to say. Because Client itself has all the Resources I want to have access to.
I am using Authorization Code Flow for authentication & authorization.
Questions:
Does access token have any role in this case? If yes, what?
How am I going to practically use the access token? Since the client itself is the resource server, there is nothing to which I need to send access token to.
I guess you get an ID token which contains all the information you need for authentication of a user. If not, you can use the access token to get the user info. If this is all the information you need, then the access token is not needed anymore. This happens, because OAuth2 is a permission delegation protocol, not an authentication protocol in a first place.
When you have the user info, you can implement between the browser and your ASP.NET backend in any way. You can take a look at the OAuth 2.0 for Browser-Based Apps RFC.
In this case you should use Client Credential flow instead of Authorization Code flow.
In Client Credential flow, your application would send your client id & client secret to Authorization Endpoint directly and asking for access token. Authorization Code is not needed in Client Credential flow. Details as below
An authorization code flow typically need your client redirect
resource owner to authorization endpoint and get a authorization
code from authorization endpoint, client than uses this code to get
access token, at the end of the day client uses access token to
access protected resource.
In Client Crendential flow. your client app is actually the owner of
your resource. So no need to asking for a authorization code. direct
uses its own client credential to get access token from
authorization endpoint and use that access token to access protected
resource(Resource server)
I have been reading about OpenId Connect and their flows that are implicit flow, authorization code flow and hybrid flow.
I know that for example, the implicit flow is kind of insecure and should be used just in public clients like SPA application.
Now I´m trying to understand the Hybrid Flow that can be used for non-public applications like .Net MVC applications where you have a backchannel communication and thus you can save a secret password.
Reading about the Hybrid flow I know that it has 3 different types of response_type that can be:
code id_token
code token
code id_token token
For me, the best response_type would be code id_token where I can get the code in the front channel and then send that code to the Identity Server Provider and get the access token through the backchannel.
I've been searching for information on a real-world application of response_type=code id_token token, or code token, but other than reading that in these flows the first token/s are issued by the authorization endpoint which is the front channel and the final tokens that are issued by exchanging the authorization code are issued at the token endpoint, which is the backchannel and thus inherently accepted as being more secure, I fail to understand what you would use this for. Any information would be gladly accepted.
Why hybrid flow? The oft-documented rationale is that your app can immediately have info about the user via the id_token while the access token acquisition is still in flight. Technically this is true but it's still rarely used in the wild.
One real-world example is a Financial-grade API (FAPI) profile developed by a working group under the umbrella of OpenID Foundation. It recommends hybrid flow for security reasons. It's worth noting that the channel split "feature" of the flow is not enough on its own to provide the desired security properties, more "cooperation" from other moving parts is needed. From FAPI implementer's draft part 2:
This profile describes security provisions for the server and client
that are appropriate for Financial-grade APIs by defining the measures
to mitigate:
attacks that leverage the weak binding of endpoints in [RFC6749] (e.g. malicious endpoint attacks, IdP mix-up attacks),
attacks that modify authorization requests and responses unprotected in [RFC6749] by leveraging OpenID Connect's Hybrid Flow that returns
an ID Token in the authorization response.
and details
8.3.3 Identity provider (IdP) mix-up attack
In this attack, the client has
registered multiple IdPs and one of them is a rogue IdP that returns
the same client_id that belongs to one of the honest IdPs. When a user
clicks on a malicious link or visits a compromised site, an
authorization request is sent to the rogue IdP. The rogue IdP then
redirects the client to the honest IdP that has the same client_id. If
the user is already logged on at the honest IdP, then the
authentication may be skipped and a code is generated and returned to
the client. Since the client was interacting with the rogue IdP, the
code is sent to the rogue IdP's token endpoint. At the point, the
attacker has a valid code that can be exchanged for an access token at
the honest IdP.
This is mitigated by the use of OpenID Connect Hybrid Flow in which
the honest IdP's issuer identifier is included as the value of iss.
The client then sends the code to the token endpoint that is
associated with the issuer identifier thus it will not get to the
attacker.
8.4.3. Authorization response parameter injection attack
This attack occurs when the victim and attacker use the same relying party client.
The attacker is somehow able to capture the authorization code and
state from the victim's authorization response and uses them in his
own authorization response.
This can be mitigated by using OpenID Connect Hybrid Flow where the
c_hash, at_hash, and s_hash can be used to verify the validity of the
authorization code, access token, and state parameters. The server can
verify that the state is the same as what was stored in the browser
session at the time of the authorization request.
For a more technical description of these two attacks and countermeasures, see Single Sign-On Security – An Evaluation of OpenID Connect
For a realllly detailed description, take a look at OIDC Security Analysis paper.
The hybrid flow allows the backend to continue to act on the user’s behalf in an offline way (when the user is no longer present sending requests by browser) or independently of the frontend... doing other stuff in parallel. It can use the back channel exchanged refresh token to continue to get a new access token and work indefinitely.
I very clearly understand the OAuth2 token exchange flows and roles. What I'm not clear about is how it maps on real world scenarios. If I have a website which acts like a GUI portion (Client) that communicates to the backend rest API (Resource Provider), it requests token from Auth server to authenticate to RP. The token usually carries scopes the describe user's permissions or roles as they would be enforced by the RP. However, the GUI usually needs to make decisions based on which scopes/roles have been granted to the token. On the one side it looks like it should be introspecting the token to figure out this information to "adapt" UI to match user's permissions. On the other, tokens are not required to be readable, they might be opaque. It seems like authorization decisions are being done on both Client & RP, which would seem to indicate client is also a secondary RP? What is the intended pattern for GUI to receive roles/scopes that the user granted it access to?
Are you talking about OAuth2.0 or OIDC or both? You've tagged openid so I'll assume both.
It seems like authorization decisions are being done on both Client &
RP
An OAuth2.0 client is an OIDC relying party. They are the same thing.
If you are using the hybrid grant - i.e. you are using OAuth2.0 with OIDC to get an access_token and an id_token then your id_token will contain information your client (relying party) can use. It is a JWT token and has an information format which you can rely on. It's also transparent.
The access_token on the other hand may be opaque, it may not - either way it is for your client to pass on to your resource server and not to try and use itself.
The access_token should contain scopes related to what your client can access on the resource server (your backend rest API), whereas your id_token should contain claims related to who the user is, when and how he authenticated and any other identity claims about him supplied by the Identity provider / Authorisation server. These claims may allow your client to tailor the GUI as required.
I'm learning about O Auth 2 from here
I was wondering in the step of "Authorization server redirects user agent to client with authorization code", why doesn't the server just give the access token instead? Why give an authorization code that then is used to get the access token? Why not just give the access token directly? Is it because there there is a different access token for each resource so that you need to go through O Auth again to access a different resource?
The authorization grant code can pass through unsecured or potentially risky environments such as basic HTTP connection (not HTTPS) or a browser. But it's worthless without a client secret. The client can be a backend application. If the OAuth2 server returned a token, it could get compromised.
There is another OAuth2 flow - the Implicit flow, which returns an access token right after the authentication, but it's designed mainly for JavaScript applications or other deployments where it's safe to use it.
If a malicious app gets hold of the client id of your app(which is easily available, for example one can inspect the source), then it can use that to retrieve the token without the use of the client secret. All the malicious app needs to do is to somehow either specify the redirect URI to itself or to tap into the registered redirect URI.
That is the reason for breaking the flow as such. Note, when the client secret is not to be used as in SPA (Single Page Apps) or Mobile Apps, then PKCE comes to the rescue.
There is a reason for breaking up the authorization flow so as to keep the resource owner's interaction with the authorization server isolated from the client's interactions with the authorization server. Therefore we need to have two interactions with the authorization server. One in which the resource owner authenticates with it's credentials to the authorization server. And another where the client sends in it's client secret to the authorization server.
Please also see PKCE that deals with SPA (SinglePageApp)/Mobile apps.
OAuth 2.0 specifies two client types:
public (client_id)
confidential (client_id:client_secret)
and section 2.2 says:
The client identifier is not a
secret; it is exposed to the resource owner and MUST NOT be used
alone for client authentication.
While it is clear to me that public clients are primarily used for the implicit flow, there is more to this than it seems. When performing the auth code flow, we first request the authorization endpoint with our client_id, no secret required. Then, after getting the user's consent and the authorize code, we request the token endpoint. According to spec, we are able to request this endpoint without a client_secret:
client_id
REQUIRED, if the client is not authenticating with the
authorization server as described in Section 3.2.1.
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.
...
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 basically this section says that we are able to request this endpoint without a client secret. Now, it doesn't say anything about refresh tokens other than that those may be included in the request.
Refreshing an access token mentions:
Because refresh tokens are typically long-lasting credentials used to
request additional access tokens, the refresh token is bound to the
client to which it was issued. 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.
So basically we're allowed to refresh the access token without client authentication.
Now, what confuses me is that the implicit flow does not allow issuing of refresh tokens:
The authorization server MUST NOT issue a refresh token.
It doesn't say explicitly why we can't do that, only that we're not allowed to. My reasoning is that this isn't allowed because the client can't be trusted. But since the authorize code flow is allowed for public clients, why do we actually need the implicit flow, if the same thing can be achieved with a public client, plus getting a refresh token?
I'd be very glad if someone could clarify this.
You are allowed to request/refresh access token without client secret at your own risk. Or we can say it depends on your security requirements. The spec only clarifies client authentication for confidential clients, basically if the client is confidential. it MUST be authenticated by the server.
For public clients, the spec says:
The authorization server MUST NOT issue client passwords or other
client credentials to native application or user-agent-based
application clients for the purpose of client authentication.
So public clients can't even have a secret to be authenticated with. And then the spec also says:
When client authentication is not possible, the authorization server
SHOULD employ other means to validate the client's identity -- for
example, by requiring the registration of the client redirection URI
or enlisting the resource owner to confirm identity. A valid
redirection URI is not sufficient to verify the client's identity
when asking for resource owner authorization but can be used to
prevent delivering credentials to a counterfeit client after
obtaining resource owner authorization.
Also you may look at PKCE.
Get back to your question, I think you are misunderstanding:
According to spec, we are able to request this endpoint without a client_secret.
Not quite right, you must authenticate confidential client and you can't authenticate public client using a client secret (it does not have one).
The authorization server MUST NOT issue a refresh token.
I think it is all matter of security. In implicit grant, we are operating under a presumably unsafe environment. Exposing refresh token could harm your system, since we already expose access token in this grant type (Please read security consideration for access token).
But since the authorize code flow is allowed for public clients, why do we actually need the implicit flow, if the same thing can be achieved with a public client, plus getting a refresh token?
They are meant for completely different use cases. From https://oauth.net/2/grant-types/implicit/
The Implicit grant type is a simplified flow that can be used by public clients, where the access token is returned immediately without an extra authorization code exchange step.
It is generally not recommended to use the implicit flow (and some servers prohibit this flow entirely). In the time since the spec was originally written, the industry best practice has changed to recommend that public clients should use the authorization code flow with the PKCE extension instead.
Lastly, I suggest you to play with this site to get a better understanding of different grant types.