Customize OAuth authentication in Spring Boot 2 - java

I'm currently in the process of implementing an OAuth2 authentication into a Spring Boot application (using the latest Spring Boot Version 2.0.1). I followed the tutorial from http://www.java-allandsundry.com/2018/03/spring-boot-2-native-approach-to-sso.html which already put me into the lucky position where the authentication itself is up and running.
However after the authentication using OAuth2 (I'm using Google as authentication provider for now) I would like to enhance the Principal(or any other object accessible to the application) with additional data.
The basic usecase is like this:
Perform OAuth2 authorization.
Check the user infomation returned from the OAuth provider.
If a user with the matching ID from the OAuth provider can be found in a local database then enhance the Principalwith that user information and proceed.
If a user with the matching ID from the Oauth provider can not be found in the local database then show an error message and block the login.
Step 1 Is working fine but I cannot find any way to add a listener, an interceptor or any other kind of configurative element into the default Spring processing that would allow me to do steps 2-4.
I already looked into the multiple configuration options inside the WebSecurityConfigurerAdapter and several other source, so far without success. The closest thing I found online was using a PrincipalExtractor but that doesn't seem to be supported any more since Spring Boot 2.
Any idea of how I can perform the interception and inject my additional logics?

Related

Keycloak and SpringBoot

I started playing with Keycloak, but I have a question. While reading articles, I always found examples where a client (let's say Angular) is logging in on Keycloak, it gets a bearer and then it send the bearer to the SpringBoot application. The backend, so, validates that the bearer is valid and, if so, it allows you accessing the desired endpoint.
But it's not enough in my opinion. I don't need just to login, I would need the entire functionality - let's say I have a backend application and I need a user. I could have a basic todo-application, how do I know for which backend user I am actually accesing an endpoint?
Straight question: how can I bind my own backend user (stored in the DB from backend) to the one from Keycloak?
What is the best way to do it? The only thing that I found online and into the Keycloack documenation is that I could move the logic of logging in from client (Angular) to backend (SpringBoot). Is this the way to go?
Imagine like I'm creating my manual /login endpoint on backend on which I would then call the Keycloak server (Keycloak REST client?) and I would pass myself (as a backend) the bearer to the client.
Please help me with an explanation if I'm right or wrong, what's the best practice, maybe help me with an online example, because I just found out the too easy ones.
OpenID tokens are rich
Keycloak is an OpenID provider and emits JWTs. You already have the standard OpenID info about user identity in the token (matching requested scopes), plus some Keycloak specific stuff like roles plus whatever you add with "mappers".
All the data required for User Authentication (identity) and Authorization (access-control) should be embedded in access-tokens.
How to bind user data between Keycloak and your backend
In my opinion, the best option is to leave user management to Keycloak (do not duplicate what is already provided by Keycloak). An exception is if you already have a large user database, then you should read the doc or blog posts to bind Keycloak to this DB instead of using its own.
Spring clients and resource-servers configuration
I have detailed that for Spring Boot 3 in this other answer: Use Keycloak Spring Adapter with Spring Boot 3
In addition to explaining configuration with Spring Boot client and resource-server starters, it links to alternate Spring Boot starters which are probably easier to use and more portable (while building on top of spring-boot-starter-oauth2-resource-server).
I Also have a set of tutorials from most basic RBAC to advanced access-control involving the accessed resource itself as well as standard and private OpenID claims from the token (user details) there.
Tokens private claims
For performance reason, it is a waste to query a DB (or call a web-service) when evaluating access-control rules after decoding a JWT: this happens for each request.
It is much more efficient to put this data in the tokens as private claims: this happens only once for each access-token issuance.
Keycloak provides with quite a few "mappers" you can configure to enrich tokens and also allows you to write your own. Sample project with a custom Keycloak mapper here. This is a multi-module maven project composed of:
a custom "mapper" responsible for adding a private claim to the tokens
a web-service which exposes the data used to set the value of this claim
a resource-server reading this private claim to take access-control decisions
The simplest way to do it is to consider that the job of storing users will be delegated to your Keycloak server. But you can implement some roles and checks manually with in-memory or any database of your preference too.
I invite you to follow some documentation about OAuth 2 and Keycloak, to make requests to get a valid token for a time period and to make others request inside that time period to get datas. You can use CURL to make requests or web/software tools like Postman.
Be careful, a lot of Keycloak Adapters are deprecated ones since some months.
I would echo BendaThierry's comments. Look into OAuth2 and Keycloak. The Bearer token you receive from Keycloak will have user information in it (typically in the Claims). This way you can have user preferences or features in your backend without needing to manage the authorization and authentication that Keycloak does.
There are lots of great resource include Spring's website tutorials (like https://spring.io/guides/tutorials/spring-boot-oauth2/) and Baeldung (https://www.baeldung.com/).

Java + Microprofile - How to authenticate without authorization

Technology stack:
payara micro 5.2021.1
jakarta 8
microprofile 4.1
I'm trying to create a simple microservice with authentication in place. I created a simple angular application that only uses the google API's service with the implicit flow to generate a jwt token.
Microprofile has a library that can be used for authentication and authorization.
I tried to use it (microprofile-jwt-auth-api) and I would like to achieve authentication without any kind of authorization.
For that I'm using the annotation #LoginConfig(authMethod = "MP-JWT") in the class that extends the Application class, combined with mp.jwt configurations in microprofile.properties.
Not sure if I'm doing anything wrong, but my expectation was that any call to any resource without the authorization header should retrieve an unauthorized error.
The authentication seems to not work without the #AllowedRoles. If I add the #AllowedRoles in my controllers, the authentication starts to work. After googling, I got the idea that the #LoginConfig(authMethod = "MP-JWT") only works combined with the #AllowedRoles, which seems to be strange to me...
Also, it seems that it is possible to disable the allowed roles mechanism (https://docs.payara.fish/community/docs/5.2020.3/documentation/microprofile/jwt.html#_switching_off_rolesallowed_support_in_jax_rs) but it didn't work.
Do you have any idea? The workaround would be to create a filter and explicitly call the google API to validate and introspect the token, but I want to avoid this scenario (if possible).

IdP server over spring boot SSO

I'm trying to implement my own IdP on Spring boot. I followed the documentation of Spring security SAML to give me a clear idea but there are no good examples of this. The only part I found is
You can test IDP initialized single sign-on with URL https://idp.ssocircle.com:443/sso/saml2/jsp/idpSSOInit.jsp?metaAlias=/ssocircle&spEntityID=replaceWithUniqueIdentifier, after replacing the service provider identifier with the one configured as entityId in your securityContext.xml. It is possible to provide relayState data sent to your SP with parameter RelayState.
But this example bases on ssocircle is the IdP and the sample Java project is the SP. So I can't see any of the ssocircle configurations (what endpoints I need and other configs) and really can't find any good example of this. In some part I read that with the Spring security SAML dependency I can make my application act as an IdP, then I reread the full document I noticed this
This chapter provides essential information needed to enable your application to act as a service provider and interact with identity providers using SAML 2.0 protocol. Later in this guide you can find information about detailed configuration options and additional use-cases enabled by this component.
Basically, this document does not cover what I'm trying to do, and right now I don't even know if this dependency will help me to reach my goal or I will need to move to another library like Shibboleth project. Have you faced this issue before?

Add Oauth2 scopes (Keycloak implementation) to request header before client Authorization request fires (Sring boot + Keycloak)

I'm using keycloak as an auth server, my client app is a sring-boot one with the keycloak client adapter dependency.
One challenge I have not yet tackled, is the insertion of specific scopes on the request header before an authorization request executes (towards the auth server - keycloak auth endpoint).
Right now I've tested my endpoints (using access-tokens with limited capabilities by the use of scopes ) via curl and/or postman and they behave as expected, so I know they work. But I don't know when/how can I append them as a "scope" request header when using spring boot (mainly because that's all plumbing code that runs under the hood in spring boot).
I assume I would need to use some kind of interceptor/filter that gives me access to that request object just before "executing", but I haven't been able to find a concrete example.
Any suggestion/guidance or pointing towards relevant documentation would be greatly appreciated.
thanks in advance.
UPDATE:
Since my last post; I've tested several combinations to achieve this, and sadly none have worked, it is quite amazing that something as basic to oAuth2 like injecting scopes on the authorization request, isn't supported easily out of the box by the spring boot keycloak adapter. I've tried following approaches:
1 - Using a custom implementation of Sping "ClientHttpRequestInterceptor" . This doesn't help because this interceptor provides access to the front-channel requests (or requests reaching the app through the front-controller), it doesn't provide access to the back-channel request (of which the auth-request is part of).
2 - "ClientHttpRequestInterceptor" is usually also used in conjunction with a "RestTemplate" custom implementation. The problem here is that this would work only to those requests executed through an instance of the RestTemplate, and this is not what happens with the back-channel requests used by the spring-adapter
3 - Using Configuration objects based on springsecurity. spring-security offers usefull filters for configuration components that could help here (#Configuration, #EnableWebSecurity, #ComponentScan(basePackageClasses = KeycloakSecurityComponents.class OR #KeycloakConfiguration); This global type of configuration basically mix your spring boot keycloak adapter app with springsecurity code, and while this works fine for most cases, if you happen to use/need "policies" (By using the "keycloak.policy-enforcer-config" type of configs), then your policies will stop working, and whole set of new issues will arise.
FROM: https://oauth.net/2/scope/
OAuth Scopes
tools.ietf.org/html/rfc6479#section-3.3
Scope is a mechanism in OAuth 2.0 to limit an application's access to
a user's account. An application can request one or more scopes, this
information is then presented to the user in the consent screen, and
the access token issued to the application will be limited to the
scopes granted.
The OAuth spec allows the authorization server or user to modify the
scopes granted to the application compared to what is requested,
although there are not many examples of services doing this in
practice.
OAuth does not define any particular values for scopes, since it is
highly dependent on the service's internal architecture and needs.
It is clearly stated that scopes can be requested by the application to receive tokens with limited access, yet all on-line documentation to achieve this with the keyclock adpaters (and particularly spring boot) is almost(completely?) non existant.
some redhat's keycloak expert could offer suggesstion?

How can I create an OAuth2 secured REST API using Spring?

I have followed a bunch of guides to no avail.
I think I have a pretty simple case so here goes:
I want to create a REST API using Spring (Boot). I have a user database which I access using Spring Data and I have already prepared a UserDetailsService for it.
Now I want to add OAuth2 security using the implicit flow, however I have not been able to get this to work. I do not wish to separate the Authorization server and the Resource server since the key is to keep deployment simple.
How would you go about this?

Categories