MicroProfile JWT with multiple public keys - java

I want to secure a REST API via JWTs provided as Authorization Header in the requests. I am have a quarkus application and would like to use their official guide - https://quarkus.io/guides/security-jwt
The guide specifies:
mp.jwt.verify.publickey.location=publicKey.pem
mp.jwt.verify.issuer=https://example.com/issuer
So far so good, now we can check if JWTs are signed by a private key that corresponds to this public key. The problem I have is that I have different APIs and different OAuth integrations, let's say 3. So different API Endpoints expect different JWTs and hence also have different public keys. Is this even supported in mp?
Spring Security allows multiple WebSecurity with different #Order and integrating multiple oAuth Servers works there. How can this be done in Quarkus/MP JAX-RS?

Yes. But using a JSON Jwt Key Set:
mp.jwt.verify.publickey.location=my-pubkeys.json
The Jwt Ket Set allows to provide several public keys in row. You can also provide an URL instead.
Also, forget about mp.jwt.verify.issuer: the property expects a string representing a single issuer. This property is not mandatory, so if you really want to control the issuer you will have to control it by yourself in your request filter.
If you only have PEM files for your pubkeys, you can turn them into Jwt Key Set using PEM to JWT convertor like this one (online). Then you just have to serve the .json file.

Related

Spring Security Authorization Server

my question about new Spring-Security-Authorization-Server, i create auth-server and resource-server, and generating public and private keys in auth-server. I set jwkSetUri in resource-server, can't understand how resource-server checks token. Who understood how the verification principle works, how should I implement it correctly?
My purpose get correct implementation of new auth server and resource server.
I found the answer after reading the book how to work with asymmetric keys, we generate a token based on public and private keys in the auth-server, and we have an address for the public key /oauth2/jwks with which the resource-server checks whether this jwt is really generated by auth-server

How do protocol mappers work in Keycloak?

I am trying out an example to add user attributes to the claim. I am following the example here. I am trying to access the claim in a filter and am unsuccessful.
I would want to understand how the protocol mappers work behind the scenes, namely how and in which order are those claims from that protocol added into the token.
In Keycloak, the function of the protocol mappers is to add additional claims to a JWT besides those that are added by default by Keyloack.
Different Protocol Mapper will have different options, but for most of them you can chose to add the claims that those mappers will produce into the:
ID Token;
Access Token;
UserInfo;
I would want to understand how the protocol mappers work behind the
scenes.
Roughly, what will happen is the following the JWT is basically an encoded JSON Object based on a specific standard, Keycloak creates that object with the Registered claims (e.g., Issuer, Subject and so on), and then it will apply the custom claims (i.e., protocol Mappers) into that temporary object by the Priority Order that you have defined for that given protocol Mapper.
The end result (i.e., the token) will be a JWT with the default claims, and with the claims added with the protocol mappers.

Is it possible to check JWT validity without refresh tokens?

For a few reasons I cannot use refresh tokens on client, is it possible to implement RemoteTokenServices on ResourceServer so that it checks the token is not revoked on auth server, but get auth information like user details from JWT-token itself, not from authentication server, like default implementation does using uuid tokens?
upd: this question is not duplicate, it's about JS and general
approach, I'm fine with approach I explained, I wonder if and how I can implement it using spring boot and spring security.
JWT consists of three sections:
Header #info about used algorithm
Payload #contains data, this one is important in your case
Signature #basically a hash of the first two items on this list
You should read about Payload (and JWT itself) here https://jwt.io/introduction
Long story short, you can include public data in the payload. If it comes to the mentioned RemoteTokenServices - sure, you can do that but I'm not sure if it's a good idea. You could just add public expiration-date (or expires) property to the payload.
Also, take a look at this: https://jwt.io/

Why do we need exactly the same configuration in resource and Authorization server

I'm talking about the case when these two are separate apps. I'm not interested in merging them in one app.
So, in a authorization server we extend AuthorizationServerConfigurerAdapter class and in resource server ResourceServerConfigurerAdapter and in both we create exactly the same beans like JwtAccessTokenConverter, DefaultTokenServices etc. but mostly I don't get why do we need TokenStore in both.
Does this mean that we store for example in memory the same token in different applications?
What's the best approach to remove this code duplication? Create a library for common classes? Make request to auth server to validate the token? But how are we going to extract more info from JWT token if we don't have the decoding logic in resource server?
Does this mean that we store for example in memory the same token in different applications?
https://auth0.com/learn/json-web-tokens/
This is a stateless authentication mechanism as the user state is never saved in the server memory. The server’s protected routes will check for a valid JWT in the Authorization header, and if there is, the user will be allowed. As JWTs are self-contained, all the necessary information is there, reducing the need of going back and forward to the database.
What's the best approach to remove this code duplication? Create a library for common classes?
If you use a symmetric key:
#Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("123");
return converter;
}
JwtAccessTokenConverter, DefaultTokenServices etc will be identical beans in both resource server and authentication server, so you could have a common project for both with the declarations of these beans, and add them as a dependency in both projects.
But, if you use an asymmetric KeyPair, the beans declaration changes completely and they couldn't be the same.
You can see more information about this difference here:
https://www.baeldung.com/spring-security-oauth-jwt
Make request to auth server to validate the token?
JWT's main advantage is not having to do that.
But how are we going to extract more info from JWT token if we don't have the decoding logic in resource server?
If you use a symmetric key, you can decoding logic in resource server.
The best way to resolve this case in the microservice system - is to create some entities: API composer, authorization service and business services.
Base mechanism of this scheme is:
Firstly, you separate your requests with unauthorized and authorized with a token header. Usually, it's named something like "X-AUTHORIZATION-HEADER" or anything like this. In this header, you put your JWT-token and send it on the server's gateway, which role is performing 'API Composer' - It's some kind of router, which accept requests, and delivery them to the appropriate recipients.
In particular, API composer accepting a response, parsing headers, finding the appropriate header with a token, and sending it to Auth Service and receiving a response with user or error. And in this scheme, you need entities like JwtAccessTokenConverter and else only in Auth Service
Then, aggregated response payload will be complete, your API will send the response to the client.
I use this scheme when I developing my microservice systems, for me it's working fine.
Hope, I correctly understood your question and my answer is will help you) Best Regards.

Query string not preserved in SAML HTTP Redirect binding

We use the Spring SAML Security Extension to implement SAML in our application. We now have the following problem:
One of our customers is providing a URL for their identity provider that contains a parameter. The metadata looks like this (heavily abbreviated for brevity):
<EntityDescriptor>
<IDPSSODescriptor>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="https://idp.example.com/login?parameter=value"/>
</IDPSSODescriptor>
</EntityDescriptor>
As can be seen, there is a parameter named "parameter" with a value "value". This parameter is not present in the generated redirect URL. I debugged a bit and found out that SAMLProcessorImpl gets the MessageEncoder from the binding (which is HTTPRedirectDeflateEncoder for HTTP redirect) and delegates encoding the message. The encoder in turn does the following in its buildRedirectURL method:
// endpointURL is https://idp.example.com/login?parameter=value here
URLBuilder urlBuilder = new URLBuilder(endpointURL);
List<Pair<String, String>> queryParams = urlBuilder.getQueryParams();
queryParams.clear(); // whoops
So for some reason, the parameters are stripped intentionally and unconditionally.
Why is this the case and how can I fix this in the most efficient way?
SAML Authentication Request should be only sent by trusted entities and with parameters which cannot be tampered with. Adding a parameter in addition to SAMLAuthnRequest encoded according to HTTP-Redirect binding will mean that a potential attacker can change the value as he/she pleases and IDP will not be able to detect such change - as the parameter will not be covered by digital signature.
SAML provides a mechanism for delivery of secured content in addition to request itself called relayState - and you can set it using WebSSOProfileOptions of Spring SAML.
The above is reason the parameters are cleared (at least I believe so, this logic comes from OpenSAML library which is not written by me), but of course in case you don't mind the security implications, the approach you found is just fine.
For now I solved the problem by extending HTTPRedirectDeflateEncoder, copying the code for buildRedirectURL and remove the queryParams.clear(). Because the URL is created by simple concatenation I explicitly removing all reserved SAML parameters (like SigAlg and the like) in order to avoid potential security issues. After that, it's a simple Spring configuration change to wire everything together.
I still don't know why the list is cleared in the first place, though.

Categories