My quarkus backend is calling a rest web service which requires an access token. The access token is generated using client id, client secret and grant type client credentials. The token is valid for a couple of days.
This quarkus backend then propagates the data to an angular frontend.
I have a couple of questions:
Is there an out of the box implementation from Quarkus framework?
If not, please guide me if I should use httpclient or any other library for getting the access token.
How to check for refresh token?
How to save the access token, so that it can be used for other requests by other users?
Otherwise I end up generating an access token every time a user calls the rest service.
Since there is no answer, I will write here how I implemented this:
I use a java.net.http.httpclient to call the oauth server for getting the token with the client id and secret.
I cache the token using quarkus-cache and when the token expires, the quarkus-cache is invalidated and rebuilt with the new token.
Suggestions or better solutions are welcome.
Related
I have gone through multiple blog posts and StackOverflow questions before writing my own. I have multiple queries and none of the posts answer them.
I am using Keycloak Spring Security Adapter to secure my legacy Spring application. I referred to the keycloak documentation here and was able to have OAuth flow running for me. I am using Client Id and Secret as Client Authenticator.
For eg: Access to localhost:8080/about.htm will redirect me to keycloak login screen and after successful authentication, I will be able to view my page. I am also using the below code to read the user details from the token,
KeycloakPrincipal<KeycloakSecurityContext> kp = (KeycloakPrincipal<KeycloakSecurityContext>) auth.getPrincipal();
IDToken idToken = kp.getKeycloakSecurityContext().getIdToken();
user.setUsername(idToken.getPreferredUsername());
Now when I test this application using postman and modify the generated access token, obviously the server gives an error. Ref : How to test application using postman.
However, this is the flow :
Client sends a request to the resource server, resource server checks for a token - if it exists, the client does the validation. If it doesn’t exist or is invalid, it redirects to the authorization server (KC).
My question is,
Who is validating this token? How does postman flow throw an error
if I fiddle with the token?
Do I really need to write a JwtTokenValidator in my application for
each request? Won't that be overkill?
If I use Client Authenticator as Signed Jwt with client secret, will this validation still be required? I am not using it as it introduces latency.
Please assist.
Answer to #1:
When you use any Keycloak adapters in your application (in your case the Spring adapter for Keycloak), that's the one who does the validation and redirects to the login if necessary. As part of the validation, it checks the signature of the token issued by Keycloak. So when you fiddle with the token, the signature doesn't match, hence it throws an error.
Answer to #2
No, you shouldn't need to implement a JwtTokenValidator. The adapter does it for you and a request should reach your endpoint/URL only if it has a valid token. You may only need to do that if you have a special requirements about validating the token (e.g. checking specific claim in the token against some service). Otherwise, you can safely use the claims in the token you received from the KeycloakSecurityContext. You can even setup authorization based on your URL patterns and Keycloak will enforce them too and allow the request to pass if user has necessary roles (like this example).
Answer to #3:
That option only changes the method used to authenticate your app to the Keycloak and has nothing to do with the user's token validation inside your app. In your current setup, when your app wants to communicate with Keycloak (e.g. to exchange auth code with auth token), it authenticate itself to Keycloak with a client-id/client-secret pair (otherwise Keycloak would not know it's your app and will reject the request).
If you choose the "Signed Jwt with Client Secret" option, your client can not just use a client-secret to authenticate to Keycloak. It should support the RFC7523 specification. So it's quite complex in compare with a simple clien-secret approach. In an environment in which you trust your clients (e.g. they're all known apps developed inside the company and you're not going to support public clients to join your Keycloak and use its services) it's quite common and safe to use client-secret approach.
I have two Java Spring applications, one is working as client and other as server. Client is Spring RESTful service.
My requirement is:
Once a server wants to communicate with a client, it should send some token. The token will get validated by client. If the token is valid then client performs some task and sends success result. Otherwise the response will be like not valid token and client does not perform any task for that request.
I think what you need is JWT token, you can learn JWT token and java in JWT token, using the java lib to generate token and validate.
The way to transfer token is to add custom header in request header, so you can just add a filter to intercept the request and validate the token.
If you want use authority not just a simple token you can use spring security and JWT token, the demo and reference can see REST Security with JWT using Java and Spring Security and demo.
In my project,I using spring security+ spring session rest+ hazelcast,it's also a way to protect my rest api by token.
You can chose the method you need and if any question you can comment under the answer.
I've an angular app which calls a java rest api to get the data. We need to secure these apps by azure AD.
I'm using ADAL.js library for angular app and trying to find any library which can be used for rest api but haven't found any on the internet. All the samples are provided for webAPi which is using Microsoft's OWIN framework.
Currently my understanding is that, our angular app will call to Azure AD to get the access token and will send that to java rest api.
Its a JWT token signed by RSA private key.
I can get the public key from JWKs uri and validate whether the JWT token and its signature is valid or not. If it's valid, the rest api will send the response back to angular app
- Is it enough on rest api side? Don't we need any communication between Rest api and Azure AD ? What if someone steals the access token and use that (within its expiration period ?)
I was under impression that resource server ( java rest api) also needs to talk to Authorization server (Azure AD) but not sure if it's really required for JWT tokens.
#Deb,I found your reqirement matched this scenarios----Web application to Web API.I recommend you refer to this document(
https://azure.microsoft.com/en-us/documentation/articles/active-directory-authentication-scenarios/#web-application-to-web-api). If your front-end used the Angular App, you could use passportjs to pass Azure AD authorization. Please refer to documnet(
https://azure.microsoft.com/en-us/documentation/articles/active-directory-devquickstarts-webapi-nodejs/#6-install-passportjs-in-to-your-web-api).
Its a JWT token signed by RSA private key. I can get the public key
from JWKs uri and validate whether the JWT token and its signature is
valid or not. If it's valid, the rest api will send the response back
to angular app - Is it enough on rest api side? Don't we need any
communication between Rest api and Azure AD ?
If you got the access_token,you could call your REST API with this token in your request. You need not any communication between REST API and AAD. But please note, you need make your API application trust another application
What if someone steals the access token and use that (within its
expiration period ?) I was under impression that resource server (
java rest api) also needs to talk to Authorization server (Azure AD)
but not sure if it's really required for JWT tokens.
You also can set the expiration time in your application for the tokens. See the part 'Token Expiration' in this document(https://azure.microsoft.com/en-us/documentation/articles/active-directory-authentication-scenarios/#application-types-and-scenarios)
I'm working on a Java app that uses JavaMail. Currently, I'm trying to connect to a mail provider that uses OAuth2. The provider returns an access token and a refresh token. After sometime, my app doesn't work because the access token has expired. I now need to use my refresh token to get a new access token. However, I'm not sure how to do that in JavaMail.
Is there a way to use the refresh token to get a new access token in JavaMail? If so, how?
Thank you
You don't use JavaMail to do this, since OAuth can be used with other protocols and services. Depending on the OAuth provider, you should be able to issue an HTTP request of the proper form to get a new access token based on the refresh token.
There's some pointers on the JavaMail wiki that might help.
I'm currently building an application with Spring and I am trying to connect to an external application. The application's resources are protected by Oauth 1.0 and I already have the consumer key, consumer secret, oauth token, and oauth token secret. Is there a way to just use this information to obtain the resources or do I have to request a new oauth token every time? If I have to get a new token every time, then is there a good tutorial on how to do this? It would be much appreciated.
It depends on how the external application is built.
If the token you have is an access token and never expires - then you don't need to get a new token every time - just use it till it expires.
If the token you have is a request token - you would need to have this token authorized first (commonly by sending a web request to the application) and exchange it for an access token (commonly a successful response will contain the access token).
You mention that you have the token secret - so I am guessing it's an access token which will be valid as long as you are subscribed to the external applications service. So it seems like you might have all the information necessary to make an OAuth 1.0 request.
The best guide on the web for OAuth 1.0 I have come across is at -
http://hueniverse.com/oauth/guide/