Spring oAuth2 with JWT using different authorization and resource servers - spring

So I currently have this POC that I'm tinkering right now. I was thinking if it was possible that I can implement a Spring oAuth2 with JWT with a Authorization Server and a Resource Server both in different projects?
Flow goes like this User gets a token or passes through the Authorization Server and as long as he has the token and it's not expired he can make requests on the resource server.

I think that is the usual way to implement that. You have one authorization service providing tokens, either itself is backed by a database containing user information or maybe is asking another user service if the credentials are valid. The returned tokens can be used to make authorized request against the resource service(s).
Maybe take a look at the grant flow here.

Related

Debugging The interface between Resource Server and Authorization Server (oauth 2.0. validation access token)

There are two spring-boot apps.
client
resource-sever
there is dev okta account that is used as auth server
(those 2 apps are standard Spring Boot client -> resource-server, almost out of the box with okta setup for them, should not be problem there)
client - securely sends messages to--> secure-sever (passing the access token in the header as prove that it's authorized to call it and get data back)
(it works as expected)
But I am trying to figure out what's going on between all them, traffic wise
I'm trying to spot that moment when resource-server checks the token it got from the client that got it from the auth server.
Here is a sequence diagram of standard oauth 2.0 flow and that part that I want to debug (arrow)
auth server
And there is a communications between client, resource-sever:
There seems I can not confirm that Resource Server (from the right) does any token validation with the auth-server (okta)..?
Question: is why? From my understanding it is supposed to validate it (somehow).
I was expecting to see a call from resource-server to auth-server (otka) with the token-validation-request (ETF RFC 7662 in October 2015) like this:
How to validate an OAuth 2.0 access token for a resource server?
I was expecting, lets say, tat for every client call, resource server would check if that token the client passes is valid. Yet I do not see any calls from resource service to okta that would use the token in its requests to okta.
This comes down to the difference between JWTs and opaque tokens.
It looks like your application is using JWTs, based on the calls I'm seeing to /keys.
When using JWT authentication the resource server will query the jwks_url (in this case /keys) on startup to retrieve a set of public keys that it can use to validate the JWT-encoded bearer tokens.
Then, when the resource server receives a bearer token in a request from the client it will validate its signature against a public key obtained from the jwks_url endpoint.
This means the resource server doesn't have to query the authorization server on every request.
You can read more about this process in the OAuth 2.0 Resource Server JWT section of the Spring Security reference documentation.
The question that you linked to refers to opaque tokens.
In this setup, the resource server must call the authorization server introspection endpoint to validate the token every time.
You can read more about this process in the OAuth 2.0 Resource Server Opaque Token section of the Spring Security reference documentation.

How to access a secured API in the frontend?

There is a lot of good content on the internet that explains how to secure a Spring API with Keycloak: Create a Client that represents the API Service in Keycloak and use a link like the one below to get the access and refresh token:
<Domain>/auth/realms/<realm>/protocol/openid-connect/auth/{some parameters}
This yields both tokens. So far so good.
Now, however, I am not sure how the flow for the frontend accessing the API should look like.
Should the frontend directly access this endpoint and, therefore, obtain the access and refresh token? That would mean that the API can only have the access-type public because there is no way to store the client (the API) secret securely.
Or should there be a third server that somehow stores the refresh token for each user, that the user can call if his access token is no longer valid. This server would then use the client's refresh token (and the client secret that could be stored securely, since it would be in the backend) to get a new access token from Keycloak and would forward it to the user.
I guess the main question that I am asking is, whether the client/user should get the refresh token.
If one needs to implement a logic according to the second option, I would be interested in a link or description of how something like this can be done in Spring.
I think, in either case you need to use the Authorization Code Flow. The implicit flow, which was recommended for SPAs (frontends without a backend server) in former versions of OAuth2 must not be used anymore.
The best option is to have a backend server, so the user retrieves the auth code via redirection and the backend server exchanges this auth code with the access and refresh tokens (and keep them without forwarding them to the frontend).
If there is no backend in place and your frontend needs to retrieve and hold the tokens directly, I would recommend to use the Authorization Code Flow with a public client and the PKCE extension (which - put simply - ensures that the entity asking for the auth code is the same as the entity asking for the tokens and that the auth code was not stolen and used by a foreign entity). There are several sources with more detailed explanations, which might help you, for example: https://auth0.com/docs/flows/authorization-code-flow-with-proof-key-for-code-exchange-pkce
Hope this helps you with your architectural considerations.

Server-2-server authorizaton in microservice architecture

It's clear for me about users authorization in microservice architecture (API Gateway for handling auth, SSO, authorization microservice and so on).
Now i'm thinking about authorization request between microservices.
And there is one question - which options i have in case when i have not got a user?
For example - analytics service, which requests data from billing and builds complex reports. There is no user, but do i need authorize request from analytics service to billing?
I know that there can be endless tokens, but i think its not good idea.
What another options for authorization request between services?
In OAuth2 specification there is such thing called machine-to-machine token. Which is different than password credentials flow which is refering to your user authorization.
To create a machine-to-machine token you should implement a flow called client credentials flow. In this flow basically all services have a specific client id and client secret and with those you are making a call to your central oauth-server to get a token. As it is also required to configure client details in the central service you will have the authorization in between client calls in terms of which client could call which others. There is also configurations for the time to live for each token.
If you already have the OAuth2 setup on your side it might be easy to introduce this new flow. But if you don't to implement such a thing on your side with your own setup could be tricky. Please check https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2#grant-type-client-credentials

spring oauth 2 authorization server app share same security context with another app

I have two authorization server application ( spring boot 2.0.5 ).
The two authorization server application are similaire
When a user ask for a token, spring will register a session for that specific user and give back a token, with that token you can access to the resource of application 1 but you can't access to the resource of application 2.
My question is if there is a way to share the same security context in addion when you generate token from application 1 you can use to access of application 2 resource
What you can do is to make your applications stateless when it comes to security.
What does it mean?
Spring Security will no longer generate a session for a new logged in user. When the user logs in, you will issue him a token (e.g. JWT). Each time when the user accesses secured content, he/she will have to provide a token and your applications will verify that token with a public or private key (depending on which type of token encryption you will use - symmetric or asymmetric). In the end, you will not need to share anything, if both of your applications have same keys to verify incoming tokens.
Some tips:
A token you send upon each request to access secured resources is called "access token". Make it expirable and make it short lived (like 15 mins). Why? This token cannot be immediately invalidated unlike session which can be simply deleted. In case if someone hijacks it, it will be still able to access secured resources.
Since your "access token" is short lived, it would be annoying for a user to logs in every 15 minutes. To prolong its life, you can have another type of token called "refresh token" that can be stored in some database. This token can be immediately invalidated by simply deleting it from the database. Therefore, if someone even hijacks it, user will be able to revoke it and the hijacker will not be able to prolong his session.
References: Stateless authentication with JWT
We are also facing similar problem.
For web pages we are using SSO which cache token in clientContext and using Authorization-server-1
For making call to API-1 we are using token generated by Authorization-server-2. In this case we have create another session bean for clientContext and that is caching token (having its own oauth2RestTemplate and clientCredientialResource)
This is two legged scenario
We doing research, how to use three legged scenario for calling web/rest service, but we were not able to do so, as access token retrieval is two step process (using authorization code) and call back will execute the whole method again and not continue from line after call to rest api

How to call a protected resource on behalf of a specific user using OAuth2 and JWT token in Spring?

So we have an authentication server where the UI application gets the access token and then it communicate with API server, it's all good. Now we are building a third application which needs SSO to authenticate the same user and that is fine too.
However, there are scenarios where this third application needs to use some resources on the API server which, from my understanding, we need to get a token from auth server using client-id/secret and then send the request with the access token. This seems ok too, however I am not sure how API server is going to authorise that token (a hint on this would be great).
But the main problem is we want this request to be sent on behalf of the user. This is because API server needs to audit all user's activities. How can we achieve this using Spring Boot/OAuth2 and JWT Token?
I went through documentation and I know about #EnableOauth2Sso #EnableAuthorisationServer etc. but this scenario is not clear and I'm not even sure it's been implemented in Spring or not.
If there is no implementation for this scenario, what do you recommend? Any experience you have had on this, can you please share?
Your API server plays the role of a Resource Server. There is an annotation designed for that purpose: #EnableResourceServer. Your client app then will consume this resource using the handy OAuth2RestTemplate.
There are two approaches to properly configure the Resource Server and get this working:
Have the public key directly in your resource server app: this way when the client app try to use a token provided by the authorization server to get a resource from the Resource Server, this will verify if the token is valid by itself.
Configure the resource server to ask the authorization server if a given access token is valid and depending of the response it will allow or decline to get the resource.
I have posted a sample app on github using the first approach. There you can see the interaction between the Authorization Server, the Client and the Resource Server, as well as all the configurations you need for this implementation. Hope it helps you.

Resources