Keycloak public vs confidental client - java

I have a frontend and backend application (angular + spring boot). The frontend is served as static web content, then it sends the REST calls to the backend API on the same port.
Keycloak with OpenID protocol is used for users authentication and role management. Upon an request which requires authentication, the browser is redirected to Keycloak, user gives username and password then user roles are returned to the browser written into the access token.
Later the frontend sends this access token with every request, the backend checks the token signature against Keycloaks public key before fulfilling the request.
Currently it works fine with one public client in Keycloak. But I am required to switch to confidential client.
How is this even possible? My understanding is that confidential application requires the client secret in the token request, which can not be sent to the browser... because it is secret.
Can someone please explain?

You typically tend to move to the BFF-pattern to better secure your SPA applications so that you do not have to deal with tokens directly in the SPA application.
Do read more about the SPA pattern here:
The BFF Pattern (Backend for Frontend): An Introduction
This video is also a good intro to what you have to do:
alert‘OAuth 2 0’; // The impact of XSS on OAuth 2 0 in SPAs

Related

Spring Boot with common Authentication

I am trying to set up authentication server for spring boot application. I have multiple microservices application. Let say hospitals, patients, reports applications. I have each of microservices service application to be authenticated before allowing user to access the resources.
Can I know how can I have common authentication logic as a separate application. let say authentication application. I am planning to us (spring security with Auth 2.0 and JWT token).
For example:
When user tries access hospital dashboard page, we will check the user is authenticated
First we need to check whether user is authentication if not I need
to redirect to login service in authentication application.
Once user is logged in, then when he try to access dashboard we will
check the token is valid. If valid then allow user to access the
dashboard service.
Now user try to access patient details which is there in patient.war as a separate project, as the user already logged in we need to valid token, then we need to allow access to resources API what he is trying to access. If token is invalid then we need to redirect to login page.
Question:
I have gone through some example they have authentication server and resource server as separate application. i.e #EnableAuthenticationServer and #EnableResourceServer. But I have noted this got deprecated in latest spring boot version if I am right. Please correct me if I am wrong.
How can I have authentication functionality as common war file and let the other resource server access it before allowing the user to access the reset service API?
Which is the right way to build a microservice application?
I need some experts help to understand the best approach we need to implement authentication and authorization in latest spring boot version.
This is a relatively older question but I'll answer since it may help others.
For any microservices-based architecture, the api gateway is an important aspect and it should be there.
All your microservices will be hiding behind the gateway and any calls made to the downstream services (hospitals, patients etc) will go through the gateway.
This gives you multiple advantages.
You can add login (authentication) functionality in the gateway
You can put rate limiter to avoid DOS attacks
A single point of entry for the outside world so your clients don't neet to know the URL of each microservice
Now, the way it works is:
The client sends username/password or client_id/client_secret to the /login endpoint which is inside the gateway (for example GatewayController)
Gateway sends credentials to an "Auth-Service" which authenticates the user from a db or anywhere and creates a JWT (Oauth token)
Gateway returns the jwt back to the client
Client calls the, let's say, /patients endpoint through gateway with the jwt as header "Authorization" parameter
Gateway -> Auth-Service (To validate the token)
If invalid, 403 forbidden is sent. Otherwise, request is forwarded to the downstream service (in this case Patients-Service)
Patients-Service sends the jwt token to Auth-Service to get permissions from inside the token since we know that the token has already been validated.
Once the permissions list is received, the Patients-Service matches them with the permissions mentioned on each api (for example PatientsController)
If any permission matches, the response is served. If not, 403 forbidden is served.
To make it more clear, Auth-Service is called once when the call is for login(authentication). Auth-Service is called twice for all other api calls(validate + permissions).

How can I make my spring boot application to log in to keycloak with given username and password?

I have a spring-boot application and I am using keycloak to authenticate users. I am planning to make an endpoint in my application that waits a username and a password, it logs-in to keycloak and if the username/password is valid ask for an access token and give it back to the user.
How can I make this log-in to keycloak?
As I see I need to have a public client to make my keycloak use username/password, but this does not contain any resource_id so I need an access_token from a confidential client.
Should I ask for an access_token from the public client, and if the response code is 200 (so the login is successful) then send another request to the confidential client to get back an access_token that is actually working?
Thanks in advance.
I am planning to make an endpoint in my application what waits a
username and a password, it logs into the keycloak and if the
username/password is valid ask for an access token and give it back to
the user.
If we assume that
the Spring App is configured correctly;
the Keycloak client that the users will be authenticating against uses Authorization Code Flow (i.e., Standard flow Enabled on Keycloak), or even better Authorization code flow with PCKE
then when a user logins into your app, the user gets redirected to Keycloak for authentication. The user is redirected (probably) back to your app (if the authentication is successful), and your app receives, among others, an access token. That access token can then be used to perform actions on behalf of the authenticated user.
As I see I need to have a public client to make my keycloak use
username/password, but this does not contain any resource_id so I need
an access_token from a confidential client.
From the RFC 6749 OAuth 2.0 specification one can read:
confidential
Clients capable of maintaining the confidentiality of their
credentials (e.g., client implemented on a secure server with
restricted access to the client credentials), or capable of secure
client authentication using other means.
public
Clients incapable of maintaining the confidentiality of their
credentials (e.g., clients executing on the device used by the
resource owner, such as an installed native application or a web
browser-based application), and incapable of secure client
Since you are neither using a pure web browser application nor a mobile phone but instead a spring-boot application with a secure backend, you should use a confidential client.
You are mixing up concepts if you mean that you want to use "Resource Owner Password Credentials Grant" (i.e., Direct Access Grants Enabled in Keycloak). You can still used with your application without having to use a confidential client. With a public client the request for a token from Keycloak looks like:
POST -d "client_id=<client_id>"
-d "username=<username>"
-d "password=user_password"
-d "grant_type=password"
<KEYCLOAK_HOST>/auth/realms/<REALM_NAME>/protocol/openid-connect/token>
with a confidential client:
POST -d "client_id=<client_id>"
-d "client_secret=<client_secret>"
-d "username=<username>"
-d "password=user_password"
-d "grant_type=password"
<KEYCLOAK_HOST>/auth/realms/<REALM_NAME>/protocol/openid-connect/token>
you got the extra field -d "client_secret=<client_secret>".
Bear in mind, however, that:
The resource owner password credentials grant type is suitable in
cases where the resource owner has a trust relationship with the
client, such as the device operating system or a highly privileged
application. The authorization server should take special care when
enabling this grant type and only allow it when other flows are not
viable.

Using Keycloak as Authorization Server with Zuul as API Gateway

I'm currently building a microservice backend with Spring Boot, Zuul as API Gateway and Keycloak as Authentication and Identity Provider.
For my frontend I'm currently using Angular as an SPA with the Authorization Code Grant.
The API Gateway should validate each request (if the user is authorized) via Keycloak before sending it to the microservice.
Each microservice ( ResourceServer) should be able to get the user information for the current request by using the introspection endpoint.
What would be the correct way to implement this, or is this even a bad design and I'm on the wrong way?
Typically, you have two options:
JWT given to client: The client (Angular SPA in your case) authenticates and receives the JWT. The JWT token can be verified by an party using the Keycloak public key. It also contains a lot of user information.
JWT given to back-end: The client is given the temporary authorization code grant. It is forwarded to a backend system, which exchange it for the JWT. The backend system will need to create a user session, store the JWT in the user session and use a session ID cookie (or a similar mechanism) to match the client to the session.
The proposed architecture is a mix of both worlds. Option 1 would be more natural.
Option 1: The client authenticates with Keycloak and gets the JWT. It then attaches the JWT to each request. Zuul can check that the JWT is signed by the trusted Keycloak instance and that it has not yet expired (without contacting Keycloak). The microservice can do the same. If more than the basic user information is needed, the microservice can contact Keycloak.
Option 2: I can't tell you if option 2 is possible with Zuul. Let's assume that it is. If so, the gateway would redirect unauthenticated requests to Keycloak. Once the client has received the authorization code grant, it is redirected to the API gateway. The API gateway then contacts Keycloak to exchange the code for the JWT and saves it in a session. The client is given a session ID. When a request is forwarded to the micro service, the JWT is added to the request. The client never sees the JWT.
These descriptions assume that you are using Open ID Connect, which is supported by Keycloak. If you use an OAuth 2 setup, most things still apply but a few details are more complicated, e.g. instead of the JWT containing all the information you get an opaque token that can only be validated against an introspection endpoint.

Secure REST endpoints with service user or public user

I'm writing a mobile app that communicates to a remote Java service via REST. I have protected my (SpringBoot) web service with https protection (due to the nature of the data, it needs to be secure) but my question is about which user/password I use to secure the https calls.
Should the username and password I use in the https header be a service account that the client (mobile app) and Java service knows or should it be the public user's username and password? The easiest option is just to use a service account but this means the mobile app will have those details built into it and distributed publically (albeit in compiled form).
Going the other way and using the user's username and password means I'll have to have the logon REST endpoint open and unsecure (which is fine I guess), but it just makes it slightly more fiddly.
Good question, and I would reckon you to use token based authentication and authorization scheme. Firstly you should have a login page where client logs in by providing username and password which is authenticated by calling some remote login service which maintains it's own user store or may use an existing one in your organization if any. Upon a successful authentication, the auth service should provide the client with a valid token, which then be refreshed time to time. The mobile or web client should pass in the token to the downstream microservices when a request is sent and this token should be sent inside the Authorization HTTP header.
Exposing the username and password while passing it around the network normally not considered as a good solution and that's where token becomes handy too. Token is the normal procedure that people use to secure rest endpoints. Yous rest endpoint should intercept each and every request comes at it, passes the token to the auth provider and verifies that. If the token is valid it will allow the request otherwise it should deny it.
Security is a pretty much larger topic and you have X.509 certificates other than tokens to encrypt the data sent across the wire over https and so forth. I suggest you to take a look at the spring security documentation since that will be a good starting point. Spring Security gives lots of hooks for developers which can be used out of the box with some sensible defaults. You can use JWT style tokens, Oauth tokens and spring security supports all these different forms too.

Java: Access an API that uses SAML authentication

I have a web project that needs to pull some data from a hosted versionone instance. The versionone instance uses SAML authentication for single sign-on.
The single sign-on itself uses a username and pin+one-time password for authentication so it is nearly impossible to hard-code those values into the application.
Is there a way to handle this situation? Can I set something in the header of the request to bypass the single-signon process?
As of release 13.1, VersionOne supports OAuth2 for authentication against the API endpoints. Both the Webserver flow (where the hosted instance POSTs auth tokens to your waiting HTTP server) and the Out-of-band flow (where the hosted instance gives the user a code to copy/paste to the client) are supported.
That may be a better match for your requirements, as the SAML process is difficult to complete without a web browser and user present.
Once the OAuth2 credentials are obtained by the app, it can operate without user intervention. At any time, the user may revoke the app's permissions inside of VersionOne.
With OAuth2, the process is:
Register your app with VersionOne, thus creating a client secret
Configure the app with the client secret data from the registration
Have the app request a permission grant, which sends you to the VersionOne server.
Login to the server as the user you wish the app to act as, and accept the grant.
Copy the grant code back to the app if using the out-of-band flow.
The app contacts the VersionOne instance and exchanges the code for a persistent token.
The app can apply the token as an "Authorization: Bearer " HTTP header to achieve access to the VersionOne endpoint
If the token has expired and the request returns Unauthorized, the client may attempt to refresh the token and try again, without user intervention.
There is some documentation available on the VersionOne community site.
And a few (in-progress) examples in the VersionOne OAuth2 Examples repository
We also have a (beta) HTTP proxy that can run on your app's server, forwarding requests to the VersionOne instance after wrapping them with OAuth2 and SSL.

Categories