What are the limits of public clients in OAuth 2.0 - oauth

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.

Related

When would I use a Hybrid flow with response_type=code id_token token in OpenID Connect?

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.

Why client authentication is NOT mandatory with Authorization Code Grant and Implicit Grant in OAuth2.0

According to RFC6749 Chapter 4.1.1: https://www.rfc-editor.org/rfc/rfc6749#section-4.1.1
In the specification of Authorization Request for Authorization Code grant,
Only client_id is required for Authentication. Since client type could be public, then that means anyone can get the Authorization Code, and then use it in Access Token Request - https://www.rfc-editor.org/rfc/rfc6749#section-4.1.3. Here you only need to supply client_id (Which is public), Authorization Code (Which can obtain with NO authentication), redirect_uri and grant_type (Not for authentication/authorization purpose), and then you will be able to obtain an access token!
My question is, why there is NO any mandatory authorization/authentication procedure for this type of grant, then what is the purpose of having this type of grant? Same thing in Implicit grant.
The client authentication is not mandatory only for the clients that are registered as public client like Mobile Native Application. The Mobile Application can not hold client secret securely, hence it is not mandatory in authorization code grant and implicit grant. The client application like web application which can hold client secret securely in the server, such clients should be registered as confidential client. The clients that are registered as confidential client should present both client id and secret for client authentication.
OAuth2 server issues an authorization code after user authentication and after user approving consent with delegating rights to the client (identified by client_id). The auth code is then sent as a parameter to a client's registered redirect URI. So I don't know what you mean by "anyone can get the Authorization Code".
Public clients should be used with PKCE OAuth2 extension. Which serves as a one-time password. So even if an auth code get stolen, it cannot be exchanged for tokens without knowing the code_verifier parameter of the token endpoint.
If an attacker creates a malicious application using someone else's client_id (pretending to be the client), the auth code will still be sent to the client's redirect URL. If the attacker gets hold of this URL handler, then it's probably a problem beyond the scope of the OAuth2 protocol.

Why does Authorization Request not require client secret in OAuth2 Authorization Code Grant Flow?

In OAuth2.0 Authorization Code Grant as stated in RFC 6749, the token request requires client secret according to sec4.1.3; however, the authorization request is not according to sec4.1.1.
Does anyone know why? It seems using client secret for both authorization and token request makes the process more secure.
They are different because they are two different types of requests. 4.1.1
GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.example.com
Is used to display the actual consent screen to the user.
Once the user has accepted then the code is exchanged for an access token
>HTTP/1.1 302 Found
Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA
&state=xyz
No secret is needed because you are currently in the Authorization Code section of the document.
4.1. Authorization Code Grant
The authorization code grant type is used to obtain both access
tokens and refresh tokens and is optimized for confidential clients.
Since this is a redirection-based flow, the client must be capable of
interacting with the resource owner's user-agent (typically a web
browser) and capable of receiving incoming requests (via redirection)
from the authorization server.
Authorization Code is sometimes refereed to as the Implicit flow, as the required access token is sent back to the client application without the need for an authorization request token. This makes the whole flow pretty easy, but also less secure. As the client application, which is typically JavaScript running within a Browser is less trusted, no refresh tokens for long-lived access are returned. Returning an access token to JavaScript clients also means that your browser-based application needs to take special care – think of XSS (Cross-Site Scripting) Attacks that could leak the access token to other systems.
Basically a user implicitly trusts their pc so there is really no need for the client secret validation step. Client secret is only needed for server sided applications where the user does not have access to the server so the server must validate itself.

Is a shared secret even necessary when using RSA256 (asymmetric) signed JWT?

One often reads that the ResourceOwnerCredentials Flow is bad because there can not be a secret key involved with an untrusted client (lika a Javascript or mobile Application).
Is this even valid if the tokens are signed asymmetrically and can be validated by the client using the public key JWK (Json Web Key) provided by the OAuth 2.0 server?
You have misinterpreted the "Resource Owner Password Credentials Grant" (link to spec.).
What this flow does is, substitution resource owner's (if it's a person, it will be the end user) credentials with authorisation code. As the specification says it can be used to replace legacy systems which for example use basic authentication. And to this to be done, trust should be established between client and resource owner. Found a good article which you can read more on this link
On the other hand, Client Credentials Grant is a grant which requires client to obtain and maintain (link to spec.). And this grant is only applicable to confidential clients
The client credentials grant type MUST only be used by confidential
clients.
I believe you have confused about two different grant types. As you have already seen, mobile applications and JavaScript applications are public client. So the client credential grant cannot be used for them.
Furthermore, once can indeed validate tokens using public key but to do that one should obtain tokens by completing a valid flow.
For a confidential client, shared secret can be used to encrypt the token. But this cannot be done for a public client as they cannot maintain a shared secret.
Anyway here are use cases for using client authentication (as described in specification : Client authentication)
Enforcing the binding of refresh tokens and authorization codes to
the client they were issued to. Client authentication is critical
when an authorization code is transmitted to the redirection
endpoint over an insecure channel or when the redirection URI has
not been registered in full.
Recovering from a compromised client by disabling the client or
changing its credentials, thus preventing an attacker from abusing
stolen refresh tokens. Changing a single set of client
credentials is significantly faster than revoking an entire set of
refresh tokens.
Implementing authentication management best practices, which
require periodic credential rotation. Rotation of an entire set
of refresh tokens can be challenging, while rotation of a single
set of client credentials is significantly easier.
As a fact, confidential client allows you the flexibility of altering client authentication by changing the shared secret.

Keycloak - OpenId Connect Access types

I'd like to authenticate a legacy java (6) application against a node-js one currently secured using keycloak OIDC bearer only (both apps belonging to same realm).
I've been told to use keycloak-authz-client library resolving a keycloak OIDC JSON as below
{
"realm": "xxx",
"realm-public-key": "fnzejhbfbhafbazhfzafazbfgeuizrgyez...",
"bearer-only": true,
"auth-server-url": "http://xxx:80/auth",
"ssl-required": "external",
"resource": "resourceName"
}
However, the keycloak java client required java 8 and my current runtime is a jre6. Recompiling the lib including transitive dependencies does not looks like a good idea and I end up so using keycloak oauth2 REST endpoint.
As far as I know oauth2 I would go with a client_credentials flows exchanging a client secret against an access_token once at application initialization and refreshing / renewing when expired.
Coming to keycloak documentation :
Access Type
This defines the type of the OIDC client.
confidential
Confidential access type is for server-side clients that need to perform a browser login and require a client secret when they turn an
access code into an access token, (see Access Token Request in the
OAuth 2.0 spec for more details). This type should be used for
server-side applications. public
Public access type is for client-side clients that need to perform a browser login. With a client-side application there is no way to
keep a secret safe. Instead it is very important to restrict access by
configuring correct redirect URIs for the client. bearer-only
Bearer-only access type means that the application only allows bearer token requests. If this is turned on, this application cannot
participate in browser logins.
It seems that confidential access type is the one suitable for my needs (should be used for server-side applications) however I don't get how it is related to browser login (which is my mind is related to authenticating using third parties identity providers as facebook and co).
The confidential client settings also require a valid redirect uri the browser will redirect to after successful login or lagout. As the client I want to authenticate is an application I don't see the point.
Generally speaking I don't get the whole access type things. Is it related only to the client or to the resource owner also (Is my node.js application stuck to bearer-only as existing clients use this access type ? will it accept the bearer authentication using the access_token obtained with client_credentials flow ? I suppose it will).
Can someone clarify keycloak OIDC access type and where I went wrong if I did ?
What is the proper way to delegate access for my legacy application to some resources (not limited to a specific user ones) of another application using keycloak ?
You are mixing up the OAuth 2.0 concepts of Client Types and Grants. Those are different, albeit interconnected, concepts. The former refers to the application architecture, whereas the latter to the appropriate grant to handle a particular Authorization/Authentication use-case.
One chooses and combines those options; first one choses the client type (e.g., public, confidential), and then the grant (e.g., Authorization code flow). Both client types share some of the same grants, with the caviar that the confidential client will require also a client secret to be provided during the execution of the Authentication/Authorization grant.
From the Oauth 2.0 specification:
OAuth defines two client types, based on their ability to
authenticate securely with the authorization server (i.e., ability to
maintain the confidentiality of their client credentials):
confidential
Clients capable of maintaining the confidentiality of their
credentials (e.g., client implemented on a secure server with
restricted access to the client credentials), or capable of secure
client authentication using other means.
public
Clients incapable of maintaining the confidentiality of their
credentials (e.g., clients executing on the device used by the
resource owner, such as an installed native application or a web
browser-based application), and incapable of secure client
authentication via any other means.
As one can read the client type refers to the type of the application architecture. Why do you need those types? The answer is to add an extra layer of security.
Let us look at the example of the Authorization Code Grant. Typically the flow is as follows:
The user goes to an application;
The user gets redirect to the Keycloak login page;
The user authenticates itself;
Keycloak check the username and password, and if correct, sends back to the application an authorization code;
The application receives that code and calls Keycloak in order to exchange the code for tokens.
One of the "security issue" with that flow is that the exchange of code for token happens on the frontend channel which due to the nature of browsers it is susceptible to a hacker intercepting that code and exchange it for the tokens before the real application does it. There are ways of mitigating this but it is out of the scope of this question.
Now, If your application is a single-page application, then it cannot safely store a secret, therefore we have to use a public client type. However, if the application has a backend where the client secret can be safely stored, then we could use a confidential client.
So for the same flow (i.e., Authorization Code Grant), one can make it more secure by using a confidential client. This is because the application will now have to send to Keycloak a client secret as well, and this happens on the backend channel, which it is more secure than the frontend channel.
What is the proper way to delegate access for my legacy application to
some resources (not limited to a specific user ones) of another
application using keycloak ?
The proper grant is to use the so called Client Credential Grant:
4.4. Client Credentials Grant
The client can request an access token using only its client
credentials (or other supported means of authentication) when the
client is requesting access to the protected resources under its
control, or those of another resource owner that have been previously
arranged with the authorization server (the method of which is beyond
the scope of this specification).
Since this grant uses the client credentials (e.g., client secret) you can only use it if you have selected confidential as the client type.

Resources