Quarkus: how to authenticate between microservices? - jwt

We have a requirement where we need some service-to-service communication between two Quarkus microservices. The infrastructure is the following:
Authentication is done by another IDP application.
Service 1:
implements main domain logic
primarily used by the frontend
API is called with authenticated user (openID, JWT)
endpoints are secured with #RolesAllowed("XY")
Service 2:
should use secured API from Service 1
Service 1 API will not be called with authenticated user (execution by task scheduler and not frontend)
My main problem: if Service 2 would directly be called from the frontend, the solution would be to easily pass through the JWT token from Service 2 to Service 1. But since Service 2 is not called in the context of a user I don't have a JWT token which I can pass.
How should Service 2 authenticate with Service 1 in such a scenario?

Either you use the client credentials flow between Service 1 and Service 2, so that they can communicate securely without any user involvement. This means that they can communicate even when no user is present.
The alternative is to use Delegation Tokens, see these links
https://auth0.com/docs/tokens/delegation-tokens
https://www.scottbrady91.com/OAuth/Delegation-Patterns-for-OAuth-20
enter link description here

Related

Microservice intercommunication and authority

This is more of an architecture question and not related to any specific technology. Let's say I have 2 rest microservices. A user has authority to service1, but not service2. However, service1 needs to access service2 for some side effect.
In my situation, service1 is actually public and you do not need a JWT to access it. Service2 requires an authenticated user.
One option I'm considering is that service2 allows calls from service1, but not from the user. That could be done with a generic JWT.
Does anyone have any suggestions? TIA!
In this case, service A should have permission to call service B, with a service user, and not with an end-user. If you are using oauth2.0, you should use client credentials. It is a grant type that is used to issue tokens to an authorized application using client id and client secret as credentials.
With this approach, service A will request a token to the OAuth server to access the endpoint of service B passing its client id and client secret and the OAuth server will give a token valid for service A to consume service B

How to use JWT Auth0 token for Cloud Run Service to Service communication if the Metaserver Token is overriding the Auth0 Token

Prerequisites
I have two Cloud Run services a frontend and a backend. The frontend is written in Vue.js/Nuxt.js and is using a Node backend therefore. The backend is written in Kotlin with Spring Boot.
Problem
To have an authenticated internal communication between the frontend and the backend I need to use a token thttps://cloud.google.com/run/docs/authenticating/service-to-service#javahat is fetched from the google metaserver. This is documented here: https://cloud.google.com/run/docs/authenticating/service-to-service#java
I did set it all up and it works.
For my second layer of security I integrated the Auth0 authentication provider both in my frontend and my backend. In my frontend a user can log in. The frontend is calling the backend API. Since only authorized users should be able to call the backend I integrated Spring Security to secure the backend API endpoints.
Now the backend verifies if the token of the caller's request are valid before allowing it to pass on to the API logic.
However this theory does not work. And that simply is because I delegate the API calls through the Node backend proxy. The proxy logic however is already applying a token to the request to the backend; it is the google metaserver token. So let me illustrate that:
Client (Browser) -> API Request with Auth0 Token -> Frontend Backend Proxy -> Overriding Auth0 Token with Google Metaserver Token -> Calling Backend API
Since the backend is receiving the metaserver token instead of the Auth0 Token it can never successfully authorize the API call.
Question
Due the fact that I was not able to find any articles about this problem I wonder if it's simply because I am doing it basically wrong.
What do I need to do to have a valid Cloud Run Service to Service communication (guaranteed by the metaserver token) but at the same time have a secured backend API with Auth0 authorization?
I see two workarounds to make this happen:
Authorize the API call in the Node backend proxy logic
Make the backend service public available thus the metaserver token is unnecessary
I don't like any of the above - especially the latter one. I would really like to have it working with my current setup but I have no idea how. There is no such thing like multiple authorization token, right?
Ok I figured out a third way to have a de-facto internal service to service communication.
To omit the meta-server token authentication but still restrict access from the internet I did the following for my backend cloud run service:
This makes the service available from the internet however the ingress is preventing any outsider from accessing the service. The service is available without IAM but only for internal traffic.
So my frontend is calling the backend API now via the Node backend proxy. Even though the frontend node-backend and the backend service are both somewhat "in the cloud" they do not share the same "internal network". In fact the frontend node-backend requests would be redirected via egress to the internet and call the backend service just like any other internet-user would do.
To make it work "like it is coming from internal" you have to do something similar like VPN but it's called VPC (Virtual Private Cloud). And luckily that is very simple. Just create a VPC Connector in GCP.
BUT be aware to create a so called Serverless VPC Access (Connector). Explained here: https://cloud.google.com/vpc/docs/serverless-vpc-access
After the Serverless VPC Access has been created you can select it in your Cloud Run Service "Connection" settings. For the backend service it can be simply selected. For the frontend service however it is important to select the second option:
At least that is important in my case since I am calling the backend service by it's assigned service URL instead of a private IP.
After all that is done my JWT token from the frontend is successfully delivered to the backend API without being overwritten by a MetaServer token.

Can we setup a SAML SSO request flow through multiple Applications from IDP

I am setting up a new SAML SSO. I will be receiving the request from Client to my Application 1. My requirement is that the same SAML request should flow till Application 2 through Application 1. I was only able to find the SAML request from Client to Application 1 and Client to Application 2 over the internet. But the Flow must be like Client -> App1 -> App2. Please advise whether this setup is possible ?
If the 'App2' is a SAMLv2 compliant Service Provider, then this can not be done as it has to check the 'audience' of the SAML Assertion and this is set to the first SP.
My recommendation would be to make the App1 both the Service Provider and the Identity Provider but - a Relay Identity Provider. A R-IdP acts as a regular IdP to any app that uses it for authentication but in the same time it delegates the authentication to an actual provider.
Then, configure your App2 to use the App1 as its Identity Provider.
This way, you'll make sure that no illegal flow involving direct access to the App2 and no illegal message flow between the App2 and the actual Identity Provider.
Also, you won't try to abuse the protocol by reusing the very same token from App1 to App2 which, although technically possible, sounds like something that could sooner or later cause trouble.

Spring boot micro services rest API security

Am newbie to spring boot micro services. I have 3 micro service that are
1. Login authentication
2. User service
3. Account service.
4. UI Service
UI Service contains UI part this micro service will calls other API's. First 3 services should validate every rest api calls. I need to implement security for rest api calls that need to be global and shared across all micro services. What would be the best approach without using oauth. Because OAuth need server. Hence without this is there any way to achieve this. I googled and not getting clear view. how to resolve this
Usally you use a JWT Token. Have a look here:
https://www.toptal.com/java/rest-security-with-jwt-spring-security-and-java

How to secure REST APIs in Spring Boot web application?

I have two Spring Boot web applications. Both applications have different databases and different sets of users. Also, both applications use Spring Security for authentication and authorisation which works properly.
At any given point I will have one instance of the first application running and multiple instances of the 2nd web application running.
I want to expose REST APIs from 1st web application (one instance running) and be able to use that REST APIs from 2nd web application (multiple instances running).
How do I make sure that REST APIs can be accessed securely with proper authentication and by instances of the 2nd applications only.
If you could change your security, I would recommend you to use OAUTH2. Basically it generates a token that is used in your APP2 instances to make the API calls.
You can see more here.
https://spring.io/guides/tutorials/spring-boot-oauth2/
http://websystique.com/spring-security/secure-spring-rest-api-using-oauth2/
But if you can't change your APP's security, you can continue using your current schema. In the APP1 you can create an user for the API calls, this user only has access to the API services. In your APP2 you need to store the credentials to access the APP1. Finally you do login into APP1 and invoke the API using HTTP client, you can use Spring RestTemplate or Apache HttpComponents Client.
SSL based authentication could be an option, if you seriously thinking about the security aspects.
Assume that you REST api exposed by App 1 is over HTTPs, then you can configure the App 1 to ask the client to give their SSL/TLS certificate when they try to access this REST API (exposed by App 1).
This will help us identify that the client is indeed a client from app 2.
Two More Cents:
In case if your App 1 REST API calls needs load balancing, NGINX should be your chose. The SSL client certificate based authentication can be offloaded to NGINX and Your Spring boot app no more worry about the SSL related configurations.
The solution we went with was to secure both using an OAuth2 client_credentials workflow. That is the OAuth2 flow where clients request a token on behalf of themselves, not a calling User.
Check out Spring Cloud Security
1) Secure your services using #EnableResourceServer
#SpringBootApplication
#EnableResourceServer
public class Application ...
2) Make calls from one service to another using an OAuth2RestTemplate
Check out Resource Server Token Relay in http://cloud.spring.io/spring-cloud-security/spring-cloud-security.html which will specify how to configure an Oauth2RestTemplate to forward on security context details (token) from one service to another.
3) Service A and Service B should be able to communicate using these techniques if they are configured using the same Oauth2 Client and Secret. This will be configured in the applications' application.properties file, hopefully injected by the environment. Oauth2 Scopes can be used as role identifiers. You could therefore say that only a Client with Scopes (api-read, api-write) should have access to Endpoint A in Service A. This is configurable using Spring Security's Authorization configuration as well as #EnableGlobalMethodSecurity