How would I implement Okta Authentication in Gentics Mesh? - okta

Gentics Mesh comes with support for Keycloak built-in, but I'd like to use Okta instead.
What's best practice?
Would it require modifying Mesh source code?
Or maybe I should handle authentication in a middleware layer?
Or could I implement the AuthServicePlugin to validate a token from Okta?
https://github.com/gentics/mesh/blob/dev/plugin-api/src/main/java/com/gentics/mesh/plugin/auth/AuthServicePlugin.java
Update
I've tried using my Okta server in the mesh.yml config, but an exception is thrown.
This is the OIDC url for my Okta service -
https://{yourOktaDomain}/oauth2/v1/authorize
Unfortunately, the OAuth2 implementation seems to be Keycloak specific -
com.gentics.mesh.core.rest.error.GenericRestException: 500 Internal Server Error oauth_config_error
at com.gentics.mesh.core.rest.error.Errors.error(Errors.java:124)
...
Caused by: java.lang.RuntimeException: Error while loading realm info. Got code {404}
at com.gentics.mesh.auth.MeshOAuth2ServiceImpl.fetchPublicRealmInfo(MeshOAuth2ServiceImpl.java:451)
It looks like it's piecing together a url that won't work for Okta.
https://github.com/gentics/mesh/blob/f85dac8bf954248a6556323d792e6b849fb1d593/services/keycloak-auth/src/main/java/com/gentics/mesh/auth/MeshOAuth2ServiceImpl.java#L434
If I'm not mistaken, the implementation [MeshOAuth2ServiceImpl] can be changed to support any OIDC.

The authentication mechanism has been recently updated.
Gentics Mesh will now take the role as a resource server. It can accept any JWT as long as the public key from the OAuth server has been added.
The plugin API has been updated to provide support for custom mappings between oauth user and mesh. This allows you for example to map multiple oauth2 users to one mesh user which contains the needed roles/groups. You can also create a 1:1 mapping in which every oauth2 user will be added to Mesh.
The public keys of the OAuth server can be loaded via plugin API or hardcoded in a public-keys.json file.
You can read more on this topic here:
https://getmesh.io/docs/authentication/#_oauth2_oidc

According to the Genetics Mesh docs, OAuth2 is supported out of the box. I'd use the OpenID Connect features in Okta to get the JWT and use that within Genetics Mesh.
There's a configuration example on using OIDC with KeyCloak, but you can substitute your Okta endpoints for the provided KeyCloak endpoints.
security:
oauth2:
enabled: true
config:
realm: "master"
authServerUrl: "http://localhost:3000/auth" # Okta endpoint here
sslRequired: "external"
resource: "mesh"
credentials:
secret: "9b65c378-5b4c-4e25-b5a1-a53a381b5fb4" # application secret here
confidentialPort: 0
Also according to the docs, if you need roles mappings, you'll have to create an AuthServicePlugin.

Related

Spring Cloud - Micoservice Authentication propagation

I am building an application using microservice architecture. I am using Eureka for service discovery with Spring Cloud Gateway for request routing. For authentication mechanism I am issuing JWT tokens (in auth service). What is the best practice when it comes to propagating Authentication so I can get logged user information in each service which is after the gateway?
So far I've came up/found couple of possible solutions:
In gateway add headers for relevant user information, and in each service create filter which would take said headers and create Authentication object and store it into SecurityContextHolder. The downside of this approach is I can't just plug and play services outside my application.
Pass the token coming from the client through the gateway to the each service, where I would have JWTFilter which would validate token and extract the user information. Downside I see with this approach is I have to have jwt secret shared between each service or stored on each service, and I would have to implement JWT logic, producing duplicate code.
Final solution is having something like oAuth token introspection endpoint in auth service which would be called from each service (filter) once the request reaches it.
I implemented the filter logic for validating the user token in the gateway service, but I would like to use role based authorization on each endpoint (service) differently (ie. user service has endpoint for creating users (ADMIN), and for fetching user information (ANY ROLE)).
I opted for something like your option 2 and use spring-boot to configure JWT decoder from an OIDC authorization-server (Keycloak).
Configuring OpenID resource-servers is super easy (more options in parent folder), and authorization-server JWT public signing key is retrieved automatically by spring JWT decoder.
All that is required is ensuring that Authorization header with JWT bearer is correctly propagated between services.

custom oidc in keycloak

I have a spring based application which does authentication and authorization(oauth2 based) for a client app.I want to now use keycloak to manage my authorizations, but i want to keep my spring code. Basically i want to use my existing auth code as an external identity provider in keycloak.
I am thinking of adding changes in client app such that it receives token from my existing oauth code(which does the authentication) and then exchange this token with keycloak(for session and authorization management). How can i do this? What configurations need to be done in keycloak?
I read about token exchange in keycloak here, but i am not clear about the kind of token i need to send from my existing auth code.
https://www.keycloak.org/docs/latest/securing_apps/
Here is how OAuth2 roles are usually spread:
Keycloak is authorization-server
Spring service is resource-server
front-end is client
user is resource-owner
I have a doubt of you wanting your Spring service to be "authorization-server" as well (serve user identity). If so, I think you should not.
Keycloak (or any other OpenID provider) should be the only authorization-server. Both Spring and client(s) should be configured to use it as so.
To write it differently, Keycloak is responsible for users login and emitting tokens with user ID (subject) and rights (roles or whatever). Other tiers in the architecture (clients & resource servers) get user info from the token and apply relevant security checks (spring security annotations, Angular guards, etc.).
I published a mono-repo for a meetup with minimal sample involving a Spring resource-server and Angular (with Ionic) client talking to a Keycloak OpenID authorization-server. You might find some inspiration browsing it.

Implementing OAuth with Api-Gateway in Implicit Grant Type using Spring Cloud (Stateless)

We have Api gateway in front of auth-provider and microservices(resource servers).
In this architecture, we don't need to get the JWT by authorization_code grant type and fire two calls as we don't have external oauth clients and only client is the gateway.
There is a sample app implemented by Joe Grandja for implementing oauth with cloud spring and Api-Gateway. That is awesome but, it is working based on web-session and authorization_code grant-type.
What it means is, stateful pattern, between browser and Gateway we have JSESSIONID and active server side session in the gateway and using the session between Gateway and Auth-Provider(UAA) to store Authorization Request to get code and then token.
I don't know what is the point here to have active sessions and use authorization_code when both auth_provider and its client (gateway) are in the same domain.
The design I am thinking, is based on fully stateless pattern. Browser or mobile apps should send token for each request in the header. We get rid of cookie based authentication and CSRF could be disabled and ... also gateway doesn't need to allocate memories for session objects.
We can have multiple Auth-provider instance with single Gateway if we want and etc.
There shouldn't be any problem to implement this from scratch, but I am wondering if Spring OAuth2 support implicit grant type when we are using:
NoOpServerSecurityContextRepository.getInstance()
The default SecurityContextRepository in the Spring is WebSessionServerSecurityContextRepository and in the sample app that I mentioned above, when I changed this to NoOpServerSecurityContextRepository I am getting exception because grant type is 'authorization_code' and spring needs to store request in the session.
So, I am looking to find a implementation for implicit grant type in spring.
Thanks,

Resource Owner Password Credentials with Spring Boot

I have a legacy desktop application that communicates with a Spring Boot server (latest version 2.2.2.RELEASE). I'm using OAuth2 for authentication (provided by spring-boot-starter-oauth2-client). I want to avoid changing the client because is a legacy application. It is capable of collecting the credentials and start the session via HTTP Basic Authentication, and then keep the cookies for the session in the following requests.
Given this scenario, I think best option is to make use the OAuth2 Resource Owner Password Credentials grant. With this, we can exchange the collected credentials by the OAuth2 Tokens. We have two options:
Option 1:
Modify the client application to use the access tokens via the Authorization header. This will require to make an initial call to the Authorization Provider to exchange the collected credentials by the tokens.
Option 2:
Keep using the Spring session and store the information about the OAuth client in the server.
I found this project ALMOST does that: https://github.com/jgrandja/spring-security-oauth-5-2-migrate. It has a client (messaging-client-password) defined with authorization-grant-type: password which will activate the OAuth2 Resource Owner Password Credentials grant in Spring Boot.
It creates an OAuth2 client and stores its information in the session, then Spring is able to use that client in further requests. The problem with this project is it seems to only work as when the OAuth client is used to make HTTP requests (e. g. an endpoint that makes a call to another service) and not provide authentication to the controller. You can find more information about this in here:
Spring Security 5.2 Password Flow
Github related issues: link1, link2, link3
Exception thrown when we try to use the password client as authentication
The natural idea to overcome this is to implement a proxy and use the OAuth2 client in the requests. Well, Spring already offers a proxy solution, the Spring Cloud Gateway. But I don't know to accomplish that with this setup.
Any insights? Am I thinking correctly or should I follow a different approach?

How to implement JWT with Keycloak in Spring boot microservice acrhitecture?

I have read some articles for Keycloak spring implementation (eg: easily-secure-your-spring-boot-applications-with-keycloak) but no one mention how to use with JWT.
I have created zuul api gateway and add Keycloak adapter as described in the previously linked article. That's ok, but I want to use JWT with keycloak.
Mentioned elsewhere set the client access type to bearer-only and the session strategy to NullAuthenticatedSessionStrategy. That's enough or need something else for JWT?
So my questions:
How do I configure client on Keycloak admin for JWT?
How do I configure Keycloak in backend config file for JWT?
How do I configure Keycloak adapter for JWT?
How do I pass user info to microservice? Create filter in gateway? But how I get user info from request?
Keycloak access token is a JWT. It is a JSON and each field in that JSON is called a claim. By default, logged in username is returned in a claim named “preferred_username” in access token. Spring Security OAuth2 Resource Server expects username in a claim named “user_name”. So, you need to create mapper to map logged in username to a new claim named user_name.
In order to provide access to client (micro-service), respective role needs to be assigned/mapped to user.
In your spring boot application, then you need to configure connection to keycloak server, providing, auth url, token url, scope, grant-type, client-id and client-secret.
Afterthat, your app be able to parse JWT token, you need to create some JwtAccessTokenCustomizer. This class should extend DefaultAccessTokenConverter and implement JwtAccessTokenConverterConfigurer classes. The main logic lays in public OAuth2Authentication extractAuthentication(Map<String, ?> tokenMap) method.
Then you need to configure OAuth2 Resource Server to provide access for other micro services. For that you define here - Oauth2RestTemplate Bean.
And in the end, secure your REST API, via the standard configuration Component.
So, you can see that, it is a large work, and couldn't be described with code, show some of your work, divide it to the chunk, and ask interesting your questions.

Resources