REST client with expiring JWT and eclipse micro-profile - java

I'm writing a micro-service with quarkus and eclipse micro-profile. Part of it is reading some configuration from an REST endpoint with a simple GET. So far so easy.
The webservice endpoint needs JWT authentication. To get the token I've to call another endpoint with basic HTTP authentication. The server does not use a standard like OAuth or OpenID. I only find micro-profile examples without or only basic authentication.
So my question is, how can I implement that process with micro-profile? I need to authenticate first, put that JWT header into the RestRequest and be aware of the expiration. Maybe there is some help in the framework?
Thank you

If your auth provider uses a custom auth scheme, then you will have to write your own ClientRequestFilter that handles the process of obtaining the JWT and then passing it to the original request as auth header.
You can have a look at existing Quarkus OIDC client filter here
basically you need to implement the getAccessToken method, where you would make a request to your Auth endpoint, exchange hard credentials for a token, and then use the obtained token. To improve performance, you should store the tokens in a cache/AtomicReference with clientctx as key, so you can reuse them if they are not expired on subsequente requests.

Related

Authentication between Keycloak and Backend-Services

We use Keycloak to secure our Spring Boot based Java Backend Services. Every endpoint is secured and a bearer token is expected inside the authorization header for each request. Keycloak then validates and verifies the token. So far so good.
During the registration process inside Keycloak (we use the authorization code flow), we have different use cases in which Keycloak have to approach our Java Backend for instance to validate an access code. I would love to use the same mechanism to secure those endpoints that are exclusively approached by Keycloak. I am wondering if it is a bad idea to use a keycloak user to send an http from a keycloak spi to our spring boot backend and then ask keycloak if the given JWT is valid. This feels like a chicken egg problem.
This feels like a common problem. What is the recommended authentication/authorization process for this kind of service to service communication? I was thinking about a technical keycloak user, that is managed inside keycloak for this purpose. I am aware of the Keycloak REST API that provides an endpoint to retrieve a token for credentials. Since I am implementing custom SPIs in keycloak, I am looking for a way to generate a token programmatically. I was able to find the right Keycloak library. Does someone know how to do that?
Here are my question:
How can I secure requests that I would like to send from keycloak to our backend?
How can I generate a Token inside Keycloak without using the Keycloak REST API (since I am implementing custom Keycloak SPIs)
Is there another way to secure my backend for technical users without using keycloak?
Best regards
Michel

Create a custom identity provider and configure it with keycloak

I am working on a project where I need to create an application that shall act as an OIDC mediator between a client which only supports OIDC for authentication and a REST api. The REST api is able to generate tokens and give user info but does not support OIDC.
To achieve this I am thinking of using keycloak to handle the OIDC communication with the client and implement my own java application that keycloak can trigger to realize the authorization, token and userinfo endpoint (sort of a custom ownmade identity provider) handling the communication with the rest api.
I have created a realm in keycloak and configured the realm to use an Identity Provider Redirector with an Identity Provider I added in keycloak (user-defined OpenID Connect v1.0). In the identity provider configuration I have set all the URLs to point to my java application but the initial OIDC authorization call from the client just redirects to the redirect_uri with a #error=login_required without any of my endpoints in the java application beeing triggered.
I guess there is something I have missed.. I need to intervene the authorization flow so that I can pick up a query param from the authorization request that needs to be handled in my java application. I also need to map the token from the rest api into the token request (when this request comes from the backend of the client app), and finally map the userinfo object as a response to the userinfo request.
I really hope someone have time to point me in the right direction. Thank you so much in advance.
Edit:
I have added a sequence diagram to explain it better:
I need to intercept the authorization request call to pick up a custom query param (endUserString) that identifies the user. There will be no user login form. I need the param in my code that uses this towards the REST API. Both the token and the userinfo must be received from my APP and not from keycloak itself.
The Java Mediator may ask for a token in advance (A) and use this to access the Rest API (using a predefined clientId and clientsecret). Alternatively this token may be fetched for each method. To token must be used to retrieve customer info from the REST API (B). I want to wrap this with OIDC support without any login form. A browser will just redirect to the authorization flow with the endUserString identifying the end user. The customer info will be returned from the java mediator into keycloak responding this in the GetUserInfoRsp.
I think there might be a simpler solution than what you envisioned: implementing your own custom authenticator for Keycloak.
Keycloak has a notion of authentication flow which is a tree of authenticators than are provided by Keycloak or custom made. Each authenticator can be called to try to authenticate the user.
The most common one is the Username/Password Form which displays a login page to the user and authenticates the user if the provided credentials are valid. But you could imagine any type of authenticator such as an SMS authenticator or a magic link one.
You can find the existing Keycloak's authenticators on their repo and the documentation on how to create your own here.
In your case, you would need to implement your own logic where your authenticator would get the endUserString param from the request and call the REST API to validate the user's identity. You could fetch the REST API token at initialisation or for each request. You could also modify the user stored in Keycloak with data coming from the REST API's user info endpoint (common OIDC attributes or custom attributes).
Please note that the dev team announced Keycloak X, a sort of reboot of the project which will probably bring breaking changes to their APIs.
Also, please consider all the security impacts of your design as, from what you provided, it seems the authentication of a user will only rely on a simple query parameter which, if it doesn't change over time for example, feels like a big security hole.

Authenticating rest endpoints and the UI using Okta

We have a Java 8 backend application using SprintBoot with an embedded Jetty server.
The UI for the application is a Single Page Application built using React.
Currently I have enabled authentication by integrating with Okta using the spring security SAML extension. When the assertion is posted by Okta to my app, I create a session and the JSESSIONID is sent in the cookie.
This was fine until now when we had a very simple UI serving few UI components.
However, now we have several REST endpoints in our backend and we would want them to be authenticated as well. REST endpoints themselves are developed using Jersey.
If I understand correctly, SAML is clearly not the choice for pure REST based endpoints as SAML is mainly a browser based protocol. These REST endpoints will be called by our UI as well we want them to be independently called via Postman or something for testing.
When a client would call these REST APIs, I am guessing the client should send an Authorization header which should be checked by one of the authentication filters in the backend. After validating the client and the user, the filter should inject the user information in the SecurityContext because Jersey injects SecurityContext in all of the REST endpoints. Then it becomes easier to fetch the user from this SecurityContext.
Upon reading, it seems Okta OpenID Connect can be one choice which issues a JWT. However I am not clear on how to use this. That is, when Okta issues a JWT should our UI or any client for that matter keep sending the JWT in the Authorization header to our APIs and then our APIs in turn should send the JWT to Okta to validate it?
Question is what is the best choice to serve both, a login for the UI and a session and authenticating REST endpoints? Not to mention the REST APIs will be stateless in nature.
When a client would call these REST APIs, I am guessing the client
should send an Authorization header which should be checked by one of
the authentication filters in the backend
In OpendID Connect (OIDC), that value in the Authorization header is id_token which can be in JWT format. This id_token is issued by the OIDC server as the last step for whichever OIDC grant type you choose and applicable to your case.
Upon reading, it seems Okta OpenID Connect can be one choice which
issues a JWT. However I am not clear on how to use this. That is, when
Okta issues a JWT should our UI or any client for that matter keep
sending the JWT in the Authorization header to our APIs and then our
APIs in turn should send the JWT to Okta to validate it?
Think that you have 3 components in this architecture. Relying Party (client), Identity Server / Authorization Server / OIDC Provider and Resource Server (your backend and it's data). When Authorization Server issues and id_token to Relying Party, your Resource Server also knows this token. So when you request for data in resource server, you will present your id_token to Resource Server and it knows if it is valid id_token or not
Question is what is the best choice to serve both, a login for the UI
and a session and authenticating REST endpoints?
OIDC Provider (or Identity Server if you need more complex operation), since OIDC is Authorization (OAuth 2.0 at core) and Authentication.

java mvc authorization without spring security

My task is to use a send request and then to get some XML.
example:
request: /api/ext/data.xml
response: some XML
The application uses Spring MVC, so I just wrote controller method, and everything works OK, but I also need to implement authorization. This app does not use Spring security.
What should I do? Should I use session to save User authorization data?
You should still look at Apache Shiro and/or Spring Security. However Spring Security (and container security for that matter) are not so friendly for REST API security. For Spring you will need to implement a custom AuthenticationEntryPoint to avoid the redirect on 403. Shiro might be a little easier for REST API.
If you want to do it yourself w/o dependencies or complexities you should look into writing a Servlet Filter and/or leverage container security. A compromise might be this SecurityFilter project. However if you need Roles, ACLs etc... you should seriously reconsider Shiro or Spring Security.
And what about implementing your own HmacSha1 model (signed requests) as Amazon Web Services do?
Basics: Client signs the request with a Secret access key (SAK) and expire data, obtaining an hmac code.
Then client sends via POST the request plus some headers like hmac code and expire data and whatever you need. The server then gets your request in the controller (or interceptor), signs it with your SAK and expire time, and compares obtaining hmacs to validate user.

Spring Security OAuth2 cookies

I have OAuth2 implemented in my app with Spring Security. Currently, it works with the "access_token" request parameter. Where can I add some customization to also accept the token from a cookie?
You cannot get the token from a Cookie - using oAuth, the only way to get it is via a call to the oAuth server, getting a code, and then getting the token...
You can read the oAuth spec.
If you talk about the application-end (and not the oAuth), it might be possible.
Checking the token is the responsibility of the application that holds the protexcted resource. There, rather than getting the token from the header of the request, it can check a Cookie instead.

Categories