Quarkus Rest Service to be accessed by users from two different keycloaks - keycloak

How to implement a quarkus rest service, that is accessed by two different frontend applications, that use two different oidc providers?
So the user of Application A, calls the quarkus rest service with a
JWT Token from Keycloak A.
The user of Application B, calls the same quarkus rest service with a
JWT Token from Keycloak B.
I first thought this would be multi-tenancy. But from what I understand in multi-tenancy, the Tenantresolver, requires different routing contexts. But here the rest service has to allow both Application A and B users access to access the same resource. Could someone please help with this?

I think this requires a multi-tenant configuration.
You can configure your Rest resource as follows:
#Path(/{uniqueKeyCloakPath}/fruits)
public class FruitResource {
…
From here on, follow the guide on the Quarkus website:
https://quarkus.io/guides/security-openid-connect-multitenancy
Basically, with the TenantResolver you need to check the incoming request whether the request is coming from Keycloak-A or B and then set the url & clientId accordingly.

Related

Use single JWT Token with 2 different applications

I have 2 different applications.
Let's say A & B.
A is being used for login/signup and users related activities.
And It is also used for Generating JWT Token and validation as well.
Now, the other application B is used for some very specific operations.
I want to use the same JWT token I generate from application A to validate users and extract useful information from the token.
Can someone please suggest to me what design should I follow?
Should I use 2 different JWT validators?
Actually is nothing wrong to use service A as an Authorization Service that issues JWT tokens and the B service as a resource service
here is a posts described how to do it in ASP.NET Web API
Token based authentication

REST best practice cloud

I have a set of REST services on IBM cloud. Ingress is integrated with Appid for authentication. Ingress adds the token id & access id to the authorization header.
Now on the API side (springboot) do I need to validate the user again on every request ? will this be redundant ? If no, which appid api can be used to authorize the user. Any reference to similar example
Already gone through the example on IBM cloud site. One is about ingress & appid integration, but does not talk about REST services layer how to handle the authorization tokens there.
Another is only about spring and Appid, (does not talk about ingress)
Authentication versus Authorization is where the line is drawn. The Ingress integration with App ID does the authentication for you and your REST service (application) can be assured that the request if it comes through is authenticated. Now just because the user exists in your system and has provided the right credential does not mean that he is allowed to access the service he is trying to access or view the data he's trying to view which is where the authorization comes into play - the REST service can use the authorization tokens to figure out if the user has the right access to use the service.
Here's a good article that talks about the use of Roles - https://cloud.ibm.com/docs/services/appid?topic=appid-tutorial-roles
In any application - REST, UI or otherwise - multiple levels of security may be necessary depending on your requirements. Authentication verifies the user is who they claim to be, authorization checks what permissions the user might have. Each application might have its own rules for what the user can access.
In your case, you have authenticated the user facilitated via Ingress with AppID, which supplies a user principal (identity) to your application. However, should every user have access to all of your application endpoints? If the answer is no, then you will need an authorization model, for which a common approach is RBAC (role-based access control).
Even without an RBAC requirement, it is still wise the validate the user's principal in some form for each request. For example, perhaps the user belongs to a domain that you might not expect, or should no longer have access to this specific REST application. Your application server may have features that assist you with a simple authorization feature, or you can custom build your own validation.
At present, as the identity provider, AppID can be the store of the user's role for RBAC. However your application or application server must decide what to do with that role.
If you are looking for a Cloud-centric authorization solution, you may want to consider exploring Istio's authorization policies:
https://istio.io/docs/concepts/security/#authorization-policy
https://cloud.ibm.com/docs/containers?topic=containers-istio

OpenID Connect / oAuth: How to allow OpenId Provider to access user's data at the Relying Party (Client) side

We're planning integration between two services: A and B.
The service A is going to be an OpenID Provider, the service B relies on it to log users in and create new accounts.
The service A also provides access to its resources via REST API using OAuth authorization, the service B uses the OAuth Access Token obtained via OpenID Authorization Code Flow.
However, there are some cases when A wants to get data from B. There is an established agreement between these services, that A can access any data from B in the scope of a user that was created via OpenID Connect.
How could I design authorization for the service B API? What could A provide to B in an HTTP request?
I'm considering things like a classic API Key, but it doesn't look natural in this workflow.
There are no direct solution to your mentioned scenario from OAuth and OpenID Connect protocol perspective.
But from what you have explained, you have OAuth 2.0 access token protected services in service A. Also, A acts as an identity provider (with OpenID Connect support). If this the case, I believe you control token issuing process and validations.
One options is to enable services from B , which are protected from OAuth 2.0 access tokens. Which is similar to what you already have in A. And to consume those services, you will have some service/client implementations bound to A. What they would do is obtain tokens from A itself to communicate with B. This can follow client credential grant from OAuth 2.0 as there is no end user involvement (scenario involve service to service interaction).
This suggested solution is similar to API key usage but with added benefit of OAuth 2.0 protocol.This allows you to generate Access tokens with limited life time and allow refreshing them if required. Also, in case you want B's services to be consumed by another client, then things are straightforward.

How to use OpenID Connect for authentication and JWT for everything else

I want to use the "microservice architecture" https://www.jhipster.tech/api-gateway/ using:
my company OpenID connect provider to authenticate users from the frontend SPA
JWT for authorization (that is, JWT from the moment the user is authenticated)
I'm not sure how that's supposed to be configured, or even if it's possible at all...
There are many architectural decisions you have to take on designing full system. But if you are going to use OpenID Conenct then there are few common aspects.
First, as you have figured out you must have a OpenID Connect provider (IDP). You have several options. You may use your own IDP for this purpose. Or else your micro-services may be controlled by an API gateway (Looking at Hipster architecture it does have one) which have a built in IDP for this. Regardless, from your application endpoint, you must use id token to authenticate the end user.
Now going into micro-service consumption, I see two options you can use. If your api gateway builds security for all micro services, then gateway must do the authorization part based on access tokens. But if you are consuming micro-services directly (without interaction with a gateway) then each micro-service handle authorization individually. Both have pros and cons but it's up to you to investigate and decide.
To sum up, your SPA consume id token for end user authentication. Once authenticated, you consume micro-services using the access token (preferably a JWT as you say). Once a micro-service receive a request, it will authorise the request based on access token JWT. For this one must validate JWT claims, signature of it as well as can use token introspection against IDP which issued the token.

angular2 login page for a web client to a back-end REST service

I am writing an Angular2 client web application client as a front end for a REST services providing access to some resources.
The REST service is protected with basic HTTP auth, and allows unauthenticated access for some of its endpoints (for instance GET /freeresource), while requires user/password authentication for other endpoints (say GET /protectedresource, or POST /freeresource, etc.).
For my Angular2 client, I would like to implement a loging page allowing access to the web application with the same ":" accepted by REST service. For this I'm following this tutorial : https://medium.com/#blacksonic86/angular-2-authentication-revisited-611bf7373bf9#.myifbz656
The problem is that the above tutorial assumes that the backend REST service has an explicit /login endpoint returning an authentication token to which you post your credentials, while my REST service does not have such an endpoint, but just returns an authorization error when passed missing or wrong credentials for endpoints that require them. I didn't find any alternative article or tutorial for a situation like this.
What is the correct way of proceeding in such a case? I could "simulate" the /login endpoint by accessing for instance a protected resource with username and password read from the app login page and trying to access a protected resource GET /protectedresource, considering as a failed login if this call returns an unauthorized error, but clearly this is not a satisfying solution (what today is a protected resource could become freely accessible tomorrow, for instance), so what is a "clean" way to implement the web app login in this case?
You don't need to simulate the /login endpoint. You just need to know on the client accessing which resource requires authentication. You can implement the same "CanActivate" method from the tutorial, and write your service call to pass credentials (or use the local storage if the user is authenticated already) when you make the REST call. If your REST endpoints require authentication every time, get them from the user at the login page, store them in the local storage, then pass them to the endpoints that need authentication.