Is there a way with Spring Security to cache token introspection result? - keycloak

I have a Spring boot REST API protected by Keycloak with Spring Security.
I can't find if there is a way to prevent token introspection on every request (i.e. caching introspection result for a short period). Everytime I hit the API, token is checked upon Keycloak and this is not great for performance :(
Thanks for any advice.

This is sort of the tradeoff that you make when you use opaque tokens (which require introspection).
With opaque tokens:
OAuth 2.0 Clients can't see the contents
Authorization Servers can revoke the token at any time
The tradeoff is that you need to check with the Authorization Server on every request to make sure the token hasn't been invalidated.
With JWT:
OAuth 2.0 Clients may inspect the contents of the token
The JWT carries its own expiry information
What you get in exchange for the performance benefit of JWT is that it can't be invalidated, only expired.
So, this wasn't your question precisely, but you asked about performance, and JWT is a very common way to address the performance hit of opaque tokens.
You might also ask yourself if you need the additional security benefits of opaque tokens for every path in your application. Could you use JWT for some paths and check with the authorization server for higher-security paths?
Anyway, you asked about caching. Yes, Spring Boot publishes an instance of OpaqueTokenIntrospector for you, which you can override with one that caches:
#Component
public class CachingOpaqueTokenIntrospector
implements OpaqueTokenIntrospector {
private final NimbusOpaqueTokenIntrospector introspector =
// ... construct
#Override
public OAuth2AuthenticatedPrincipal introspect(String token) {
// call delegate introspector and cache
}
}
You could use the #Cacheable annotation on the introspect method, for example.

Related

Keycloak as IdP with own implementation of Resource Server

Is there a way of using Keycloak only to Authenticate user, but with own mapping to roles with Spring?
I would like to authenticate API Gateway in keycloak first, but then provide internal JWT Token with authorized roles inside my microservice world.
In this article, I do map Spring authorities from roles that Keycloak sets in JWTs. Is that what you are looking for?
If what you want is having a hand on access token claims, two cases:
the claim is already in the token but with a different value than what you expect (missing roles, outdated email, ...). Then, it is very likely that Keycloak admin API exposes what you need to update users data. Check that a "confidential" client with required roles is declared with client-credentials flow enabled (or declare a new one) and have relevent resource-server call admin API for updates (with WebClient, RestTemplate, #FeignClient or whatever is capable of using client-credentials flow).
the claim does not exist yet. Then, define a new Keycloak "mapper" to add a private claim. Here is a sample. You can have a look at security module to figure out how this new private claim is parsed (by ProxiesClaimSet) into an Authentication custom implementation.
In any case, the authorization-server (Keycloak) is the only place to define claims, issue JWT and sign it. JWT validation by JWT decoder on resource-server involves much more than just checking expiration date: issuer, issued-at, token integrity (server signs the payload with a private key and exposes a public one to ensure the token content was not modified), and more are verified too.
You want to make access control inside resource-servers? Great! Ensure that authorization header with Bearer access-token is forwarded by the gateway from client(s) to resource-server(s) and configure your resource-server(s) as described in the article above.
P.S.
In the article you'll also find a way to test security rules (both unit and integration) with mocked authentication. This is what, in my opnion, makes resource-server(s) a better place to implement access-control: security rules are of primary business importance and fine grained unit-testing is essential.
Other note, if you go for additional private claim(s) with Keycloak mapper(s), pay attention to pom.xml file, java/main/resources and implemented interfaces of ProxiesMapper into proxies-keycloak-mapper module.
Last, you should also follow the first 3 of those tutorials (for real: write the code and run the tests), it will take you less than an hour and will save you many more hours struggling with your resource-server(s) security implementation.

Pitfalls of securing web APIs with cookie for public clients

I am mid-way of implementing oidc/pkce implicit authorization flow in my asp.net core rest web api for a public JS client.
I almost understand how this works, but I can't exacly understand what are the biggest issues with another approach - if I were to use the default cookie (or session) authentication provided by ASP Identity.
I find it hard to google this topic. Can I please ask for some hints / pointers to articles?
Plain cookie authentication is still used, even when you use token based authentication.
After the OpenIDConnect client receives the final tokens, it will by default create a classic session token that contains the user details and claims. Optionally you can also store the ID/Access/Refresh tokens inside this cookie.
The cookie is encrypted so it can't be tampered or hacked.
The benefit of using OpenIDConnect is when you have multiple clients and/or API's involved and you want a standardized way to handle this. Doing the plain cookie approach with many different services is hard to make secure.

Decoding Keycloak JWT Token

I'm trying to validate (and read roles from) a JWT Token. Sadly I can't use any adapter or auto configuration due to my overall application architecture.
It's no problem to decode the token like any other JWT Token, but I wonder if there is a library from Keycloak to archive this goal. (For example Just Parse the token to something like a KeycloakJWTToken and verify it by grabbing the secret from Keycloak Server or so)
Any easy-to-use client or so?
I'm using the Jose4J library:
https://bitbucket.org/b_c/jose4j/wiki/Home
Reading the claims inside a JWT token is straightforward:
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
public void parseJWT(String token) throws Exception {
JwtConsumer consumer = new JwtConsumerBuilder()
.setSkipAllValidators()
.setDisableRequireSignature()
.setSkipSignatureVerification()
.build();
JwtClaims claims = consumer.processToClaims(token);
System.out.println("* Parsed token: "+ claims.getRawJson() );
System.out.println("* Expiration date: " + new Date(claims.getExpirationTime().getValueInMillis()) );
}
More examples are available on GitHub:
https://github.com/pvliesdonk/jose4j/blob/master/src/test/java/org/jose4j/examples/ExamplesTest.java
Last remark: you do not need a key nor a secret to parse the JWT, but if needed, you can use the server (public) key to verify the token was signed by the keycloak server you are trusting.
The JWT website is listing all libraries for Token Signing/Verification:
https://jwt.io/#libraries-io
Keycloak access tokens are indeed JWT tokens. So, you can make full use of existing JWT libraries, including for validation as stated in the Keycloak official documentation:
If you need to manually validate access tokens issued by Keycloak you can invoke the Introspection Endpoint. The downside to this approach is that you have to make a network invocation to the Keycloak server. This can be slow and possibily overload the server if you have too many validation requests going on at the same time. Keycloak issued access tokens are JSON Web Tokens (JWT) digitally signed and encoded using JSON Web Signature (JWS). Because they are encoded in this way, this allows you to locally validate access tokens using the public key of the issuing realm. You can either hard code the realm’s public key in your validation code, or lookup and cache the public key using the certificate endpoint with the Key ID (KID) embedded within the JWS. Depending what language you code in, there are a multitude of third party libraries out there that can help you with JWS validation.
Besides, in Java EE, using the Keycloak Java adapter, the roles are typically mapped on the user Principal and i.e. allows isUserInRole(). That's one of the goals.
Also it is possible to cast the Principal from the SecurityContext as a KeycloakPrincipal, then obtain in turn a KeycloakSecurityContext from it. Using the KeycloakSecurityContext you have access to both ID and Access tokens (when applicable) and can read their properties, attributes and claims.
Note that it is also good practice, and simply useful, to use the Keycloak UI to "evaluate" your tokens. For instance, you can see the generated token in the Client Scopes tab (under Evaluate), as well as evaluate your policies and permissions in the Authorization tab of your Client(s) (under Evaluate).
Cf. https://www.keycloak.org/docs/latest/server_admin/#_client_scopes_evaluate
That's probably the best way to debug and test, while setting up your Client(s).
If you select a user in the Evaluate screen, the following example data is generated:
Generated Access Token (...)
Generated ID Token (...)
Generated User Info (...)
All examples are generated for the particular user and issued for the particular client, with the specified value of scope parameter. The examples include all of the claims and role mappings used.
Source: https://www.keycloak.org/docs/latest/server_admin/#generating-example-tokens-and-user-info

CSRF and stateless APIs

We currently have a stateless REST api, authenticated by JWT bearer tokens. (each of our servers trust the incoming JWT token as long as it's unexpired, load the user, and auth using the loaded user.)
We currently store the JWT token in localstorage, for development convenience. However, we're starting to implement security and defences, and we want to change our implementation. So:
We're going to send the JWT token as an HTTPonly and secure cookie (incidentally, this means that we don't have to manage it on the client side Javascript, because, well, we can't.)
We're going to include a CSRF token in our JWT response.
A couple of questions:
Introducing CSRF introduces state to our system, in that we're going to have to share this token across all our servers. While not being a stateless purist, this does bother me a little. Are there other ways of dealing with this?
Should we change the CSRF token each time? It seems like there's still 30 mins (our timeout setting) worth of vulnerability if we don't. However, if we do, does this introduce timing issues with pages that would make multiple API calls?

OAuth2RestTemplate with prefetched JWT token

JWT OAuth2 Token is prefetched from Spring Auth Server and stored in Redis Storage.
I don't want to request access token in OAuth2RestTemplate and I want to use my JWT Token for requests.
Can I do it with OAuth2RestTemplate or I should use usual RestTemplate?
The documentation for spring-security-oauth is useful here, basically the two sections: JWT Tokens and Accessing Protected Resources:
JWT Tokens
To use JWT tokens you need a JwtTokenStore in your Authorization
Server. The Resource Server also needs to be able to decode the tokens
so the JwtTokenStore has a dependency on a JwtAccessTokenConverter,
and the same implementation is needed by both the Authorization Server
and the Resource Server. The tokens are signed by default, and the
Resource Server also has to be able to verify the signature, so it
either needs the same symmetric (signing) key as the Authorization
Server (shared secret, or symmetric key), or it needs the public key
(verifier key) that matches the private key (signing key) in the
Authorization Server (public-private or asymmetric key). The public
key (if available) is exposed by the Authorization Server on the
/oauth/token_key endpoint, which is secure by default with access rule
"denyAll()". You can open it up by injecting a standard SpEL
expression into the AuthorizationServerSecurityConfigurer (e.g.
"permitAll()" is probably adequate since it is a public key).
To use the JwtTokenStore you need "spring-security-jwt" on your
classpath (you can find it in the same github repository as Spring
OAuth but with a different release cycle).
Accessing Protected Resources
Once you've supplied all the configuration for the resources, you can
now access those resources. The suggested method for accessing those
resources is by using the RestTemplate introduced in Spring 3. OAuth
for Spring Security has provided an extension of RestTemplate that
only needs to be supplied an instance of
OAuth2ProtectedResourceDetails.
This basically means to me that you'll use the same spring-security-jwt JwtAccessTokenConverter class in both the authorization server and the resource server and that the token services in each need to be setup with the JwtTokenStore(). The extension to the RestTemplate class they're referring to is the OAuth2RestTemplate from spring-security-oauth2. You'd use it in your resource server with it's JWT smarts being provided by an equivalent token recognizer.
Because the spring-security-oauth2 code is already set up to handle JWT tokens, you just need to provide a few key pieces and let the framework do the heavy lifting of inspecting the token and putting the security into scope for each protected resource.
As it would happen, someone's posted a nice example of this which goes into detail: baeldung spring-security-oauth-jwt example and here: github project of the same including how one could provide a more customized JWT (claims/payload).