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

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?

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/).

Custom login form - Spring Security

Does any of you have some example of Custom Spring Security Login form using REST Api? I am actually trying to create my own, and the problems I'm facing are:
How should be named classes, is it User and Role? Cuz I seen many different versions of it.
Where should I post JSON file with login and password?
How should it look like?
Thanks in advance for all answers and examples of your code (github or something).
REST APIs are usually stateless. It does not know something about a session. So i think you're looking for an basic auth to protect your API.
Or you could use openid connect and check the roles based on a token. This would give you more flexibility for pre conditions and post conditions processing a service call.
Here is a good example of openid connect with spring boot and google implementation. Other provider are adaptable. Baeldung - Spring Security openid connect
If you're just looking for a simple solution with basic auth, take a look here
Baeldung - Spring Security basic auth
yes, you can use form login and rest API together, but that means that your rest API isn't going to be stateless, it means that a session will be created and rest APIs are usually stateless, that's why you have to use basic auth, jwt, etc when creating a rest API, but if you really want to use rest API with form-based authentication, I made an example for you, check this link
This example uses Spring Boot, Spring MVC, H2, Spring Security with custom form login, Spring Data Jpa, but again it's not recommended to use form login for rest API.
Regarding to your questions
How should be named classes, is it User and Role? Cuz I seen many different versions of it.
It's up to you
Where should I post JSON file with login and password?
If you are using spring security form-based authentication, there no need to post a json

How to maintain usersessions in Spring Boot

So I'm busy with a Spring Boot REST server which connects to a PostgreSQL database.
My goal is to make an application which can easiliy be ported to android that is able to send a login JSON POST request and then maintain a session so that you don't require to send the credentials again for other GET requests. What are some ways that I could implement something like this?
I'm a bit confused as to what to use. Because there are so many library's, I also heard about a Spring Sessions library and Auth2. Auth2 however seems to be more applicable for integration with facebook/google login, which I do not want.
You will want to add spring-security to that spring boot in order to handle and maintain sessions. Take a look into their documentation and view this blog post to help you out. You will have some reading fun time, yeah!

Customize OAuth authentication in Spring Boot 2

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?

How to secure the Rest webservice by token based authentication?

I have created few rest services using jersey implementation.
In security concerns, service can invoke by any one. So I decided to use the token based authentication system.
I wrote one filter in spring security which handles every request before its hits the server.
One login service were created so user can invoke this service by passing the username and password for valid credentials it will generates the access token and expiry date and saves it in Hashmap and DB and returned as a response to the user.
For remaining services user have to pass the generated token in header to access the JAX-RS services.
All these process are coded by us i.e., generation,storage and expiration of the token.
Since we have some security API like oauth1,oauth2 in market is it good to provide the security for rest service by above mentioned way???
Is oauth api will suits my requirement . If it is please guide me how to achieve this ?
Please help me out with valuable suggestions ???
Thanks in advance.
We've been in a similiar position before starting with our rest api. The only difference we had no exisitng code. So basically we saw 2 choices
Run our own Tokenhandling, that what you already have
Use something existing, i.e. oauth2
Our main requirement was authentification via token and we prefered an existing solution. So we just run with oauth2 in form of spring-security-oauth2, even we are not using the whole self authorization stuff.
What i like and probably had missed in an own implementation is that a token generally identifies a user and a client combination and that clients can have rights too. Its nice to have this extra layer of security in our rest api, so i can block early on before even hitting one line of our code.
In form of spring-security-oauth2 its proven code, which works and like much of spring its customizable. Example: In our first version we did use the provided JdbcTokenstore for storing the token, but as requirements changed, we just coded our own and switched it in the config.
The disadvantage of using at least spring-security-oauth2 is that the whole authorization flow is normally webbased and needs communication between the client, the user and our app. As this would not work with our clients we had to trigger the token generation, etc ourselfs, which is doable with spring, but needed some code exploration :-)
If i had to build it again with java and where already using spring, i'd go with spring-security-oauth2 and the oauth way again. But when i had an existing working solution and dont need any of the oauth stuff i would keep the homegrown solution.

Categories