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.
Related
I have a web app (C# / Javascript) where I want to call a back-end service that I own. I want to secure that service so only my app(s) can call it. Seems like if I use Oauth on the client side, the secret is exposed? All the docs I read about Oauth give solutions when the user of the app owns the resource, not when the app itself owns it. I was looking at how google apis work, and the JavaScript libraries seem to expose the key on the client side, no?
Yes you can accomplish this with OAuth, but how you go about it depends on the details of how the data accessed via your back-end service is organized. If the data is actually user-specific, then your user really is the resource owner. In this case you would use the typical authorization code grant. With this grant type you register a client with the OAuth auth server and receive a client_id and client_secret. The client_id is, indeed, exposed in the browser, but the client_secret sits in your web app server and is never exposed. It is only sent on back-channel (non-browser) requests to your auth server. The main thing here is that only your own client web app would be registered and receive the client_id/client_secret. You simply need to not provide any public registration endpoints so no other clients can register. With this grant type, in order for your web app to gain authorization to access the user's data on the back-end service, the user would need to approve the authorization in the browser as part of the process.
On the other hand if the data you're accessing on your back-end service is not user-specific, then you can use the OAuth Client Credentials grant. With this grant type you register the client as before and receive a client_id and client_secret. The secret is stored securely on your web app server and only passed in back-channel requests. You would avoid allowing any other clients to register. Your web app can then gain authorization to your back-end service without even needing any user authorization in the browser.
I'm afraid there is no way to restrict your API to be called just by the code of your applications. Browser applications with public codes cannot hold any secret (such as certificate), that would identify them, because anyone can extract it from the code. Desktop and mobile applications compiled to bytecode are not so easy to read, but with some effort, attacker could find the secret data. That's also the reason why these applications (so called public clients) don't hold client_secret if they act as OAuth2 clients. They use a one-time secret instead - PKCE.
What you can do, is to check the audience (what client ID the token was issued for) of an access token sent from a frontend application to your backend. You can get this info either from the token introspection endpoint (aud attribute) or from JWT attributes if the token is of JWT type.
I'm trying to understand how to best apply the OAuth 2.0 grant types to a microservice architecture I am working on. Here's the situatation...
I have a Single-Page Application/Mobile App acting as a client running in a web browser (browser acting as the user agent) or mobile phone. I use the Implicit Grant defined in RFC 6749, section 4.1 to authenticate a user and acquire an access token that the app uses to access some externally exposed API.
The architecture I am dealing with is a collection of microservices that call on one another. For example, consider an externally exposed API serviceA and internal APIs serviceB and serviceC. Let's say serviceA depends on serviceB which subsequently depends on serviceC (A --> B --> C).
My question is, what is the typical authorization flow for this situation? Is it standard to use Implicit Grant for the SPA to acquire an access token and then use the Client Credentials Grant defined in RFC 6749, section 4.4 to acquire an access token for the machine to machine interaction between serviceB and serviceC?
For your single page application, use the Implicit grant, which is designed for browser applications - they cannot hold any secrets and with the Implicit grant, the tokens stay in the browser (because it's in the hash part of the redirect URL).
The mobile app, take a look at the OAuth 2.0 for Native Apps, it recommends the use of the Auth code grant. It also describes implementation details for common platforms and security considerations.
There is a new grant described in the OAuth 2.0 Token Exchange RFC that would suit your needs for chained calls between services:
... An OAuth resource server, for example, might assume
the role of the client during token exchange in order to trade an
access token, which it received in a protected resource request, for
a new token that is appropriate to include in a call to a backend
service. The new token might be an access token that is more
narrowly scoped for the downstream service or it could be an entirely
different kind of token.
But I don't know whether Auth0 supports it. If it doesn't, I would probably pass the original access token from serviceA to serviceB and serviceC. The internal services could be secured at the network level too (e.g. they could called just from other services).
If serviceB and serviceC are internal and will never be called from an external client then the Client Credentials Grant would be a good candidate. As the client is also a resource server too.
You could also look at passing the same bearer token between services, providing the SPA (which requests the token initially) obtains consent for all scopes which may be used by the other services and the "audience" of the token must allow for all the possible resource servers (services).
I don't think either are best practice and there are tradeoffs with both ways.
I would honestly recommend for each backend service to implement the Authorization Grant. That is have an endpoint exposing the redirect to your provider. Then for each frontend app go to that endpoint to trigger the OAuth flow. After the flow has been completed handle the Authorization part in the callback url and return a token which will be stored on the frontend somewhere.
Hope this helps.
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.
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.
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.