I am working on an application with spring boot backend, that I want to secure with OAuth2 using implicit flow. The front end will be angular (SPA). For the initial phase I will have Authorization and Resource server on the same instance, but want to be able to seperate it later on.
I do understand that authorization "takes place" on the Authorization server and then a token is used to access resources. But how do I add a new user to the system? Should there be a registration (password reset etc.) endpoint on Authorization server or the Resource Server?
It makes sense to put it on Authorization server, so when I add a new application that uses it will be able to add a new user to the system.
From other point of view the Authorization server should be used only for authorization, so user creation could be delegated to a resource server.
Usually the registration process is implemented in the resource server, so this endpoint and similar endpoints like retrieving a forgotten password, resetting the password etc all of them lives in the resource server, as they are part of the logic of your application, not part of the authorisation itself.
Related
I have a front end (angular) with login form, a back-end for that angular application as my OAuth client (spring dependency) then I have a third application that is the Authorization server and finally the forth is the ressources server.
So I want to know is there is any way to jump the redirect to /login from the authorization server?
I want to login the user with angular login page, then make a get with my OAuth client (spring) for the authorization code flow and then, since i'm not authenticated, instead of getting redirect, I want to get an error "401" and then send a post request with my OAuth client (spring) to the auth server again to login the user that have sent the data previously in angular login page.
Essentially I just wanted to login to my auth server with a custom page that exists in the front end application and let the backend build specially for that front, take over the flow.
You want seamless integration between login form and the rest of your Angular app? Share your CSS between Angular (public) client and authorization-server embedded (private) one, don't implement login in public client.
You might need to better grasp OAuth2 concepts.
Login, logout and user-registration are authorization-server business. Leave it there. Reasons are related to security and just being future-proof: what if you want to plug additional clients to your system (mobile apps for instance)? Are you going to implement login, logout and user-registration again and again? What if you have to introduce multi-factor authentication at some point? Would you break all clients at once?
Your "backend" (Spring REST API secured with OAuth2) is a resource-server, not a client. Make sure it is configured as so: depends on spring-boot-starter-oauth2-resource-server (directly or transitively). This is where the HTTP status for missing (or invalid) authorization is handled. The way to do it depends on your resource-server being a servlet or reactive app. The libs in the repo linked just before do what you want by default (401 instead of 302).
In your case, client is Angular app. I hope you use an OAuth2 client lib such as angular-auth-oidc-client to handle:
authorization-code flow (redirects to authorization-server, back from authorization-server with authorization-code and tokens retrieval with this authorization-code)
refresh-token flow (automatic access-token refreshing just before it expires)
requests authorization (add Bearer Authorization header with access-token on configured routes)
What my Angular apps do for login is just redirect users to authorization-server "authorization" end-point and then just wait for a redirect back to "post-login URL" with an authorization-code. How this code was obtained is none of their business (can be a login form, a "remember-me" cookie, some biometry, etc.).
Also, I have to admit that I don't use Spring's authorization-server. I prefer mature / feature-full solutions like Keycloak, Auth0, Okta, etc. which come with much more already implemented: multi-factor authentication, integration with LDAP, identity federation for "social" providers (Google, Facebook, Github, etc.), administration UI, ...
As ch4mp said, it's best to leave all the authentication and authorization logic and pages to the Spring Authorization Server, it's pretty easy to customize and configure all the user accessible pages (login, authorize, etc...) with Thymeleaf, you only have to bring in your CSS to unify the design.
There was a great demo in last year's Spring One which seems like something you'd like to achieve, you can find the code in this repo.
They used Spring Cloud Gateway as a means to run the Angular SPA in the flights-web app, configuring it as the OAuth client. Following this path you can route all calls to your backend API through the gateway's WebClient.
I am currently developing using spring security oauth2.
Currently, the frontend is SPA, and it is developed as react that operates with client side redering.
My rest api has the spring security starters libraries. But I don't know how to use oauth2 flow provided by spring.
So my question is: Can I use spring security as IAM to protect my web and api?
Does spring security have the known oauth2 grants and how use them ?
Implicit grant
Client Credentials Grant
Password grant
Don't use implicit grant
It is not recommended to use the implicit flow (and some servers prohibit this flow entirely) due to the inherent risks of returning access tokens in an HTTP redirect without any confirmation that it has been received by the client.
source: https://oauth.net/2/grant-types/implicit/
With implicit grant, access token is returned immediately without an extra authorization code exchange step. This extra step is usually performed in your backend.
Web > token > Api
SPA frontend and its Rest Api is a very common approach, used since simple startups until big companies. The flow summarized is:
Your users will start the web application.
As they were not signed in before, you web app will show them a login screen (a page provided by the authorization server).
After authenticating, a consent form is showed to the user.
After user consent, the authorization server will send you an authorization code.
The web app will exchange this code for a token.
After getting back this token, the web app store it in the client(browser) and send it as a header when apis needs to be consumed.
Your private rest apis must validate if token of the web app (header) is valid by sending it to one endpoint of the authorization server
If token is valid, your api rest is allowed to respond to the web client. For instance a json with products, employes, some update of customer order details, etc
For this flow to work, you will need:
web spa with a hint of backend. Backend is required because you cannot have a proper user session in static solutions like apache or nginx.
authentication and authorization server: Known as identity and access management (IAM) or some third app which provide you the basic oauth2 endpoints to manage a proper security for your apps.
your apis: foo-api , bar-api, baz-api, etc
spring security
In the minimal scenario in which:
you will have only one web + one rest api, and nothing more in the future (mobiles, iot, etc)
you don't have an authentication/authorization server
you have a mix of functional apis (employee, products, etc) and its security (spring-security) in just one artifact
you don't need user session in your web
you don't need a logout feature
Flow could be reduced to:
Your users will start the web application.
As they were not signed in before, you web app will show them a login screen (a page provided by spring-security).
After authenticating, a consent form is showed to the user.
After user consent, the authorization server will send you an authorization code.
The web app will exchange this code for a token. Since your api is using Spring security, the token generation is covered.
After getting back this token, the web app store it in the client(browser) and send it as a header when apis needs to be consumed.
Your private rest apis must validate if token of the web app (header) is valid by sending it to one endpoint of the authorization server I think the spring security chain filters handle this.
If token is valid, your api rest is allowed to respond to the web client. For instance a json with products, employes, some update of customer order details, etc
Here some samples of token generation and protected endpoints with spring security. I will try to upload a ready to use sample:
https://www.freecodecamp.org/news/how-to-setup-jwt-authorization-and-authentication-in-spring/
IAM
If you will have more applications and complex scenarios in the future, I advice you to choose some open-source iam like:
Glewlwyd,Keycloak,OAuth.io,ORY Hydra,SimpleLogin,SSQ signon,
Commercial services like:
Auth0,Curity Identity Server,FusionAuth,Okta,Red Hat Single Sign-On,cidaas.
Or try to develop a new one using pure spring-security
Lectures
Some recommended answers with more oauth2 details:
https://stackoverflow.com/a/62123945/3957754
https://stackoverflow.com/a/62049409/3957754
https://stackoverflow.com/a/57351168/3957754
https://stackoverflow.com/a/63093136/3957754
https://stackoverflow.com/a/54621986/3957754
https://stackoverflow.com/a/63211493/3957754
I have a SpringBoot Micro-Service based backend API that uses Zuul as a gateway proxy between a JavaFX Desktop Application. Right now there is no security in place, but I am looking to secure the backend with Spring Security, however, every tutorial I seem to run across seems to be based on web-apps and I haven't seen anything for my particular use case. I don't know much about spring security but would like to know if I can accomplish my goals with it, and if so, what modules or examples should I be looking for.
Goals:
Provide a way for my API to know that requests are coming from the desktop app itself, I think the technical term for this is assigning the desktop app a client id and then having the Zuul Server validate that the client id is that off the desktop app before accepting the request. This should be the case for all requests
Only allow API traffic through the Zuul Proxy, all of the downstream requests to the micro-services behind the Zuul gateway should only be accepted if they are coming from the Zuul Server itself.
Allow requests for logging in and registering as a new user without any type of security other than the desktop client id discussed in 1.
When a user provides a successful username/password on login, they are returned a JWT which is then stored in the JavaFX application and used for all of the other requests to the backend.
Configure the token to expire after a specific time frame, say like 90 minutes and provide a method for automatically refreshing an expired token as long as the users account is still valid. For this, I don't want the user to have to re-login, I just want it to check behind the scenes to make sure their account is still valid and then issue a new token if needed.
Have user based roles so certain features, methods, endpoints, etc. are only accessible to users with the valid role. Within the GUI these features will be hidden or disabled, but I would still like a layer of security on the server side to protect against unwanted access in case someone was able to modify the app.
I am just writing down answers to each of your goals :
Passing the client Id in every request from desktop application doesnt make sense, instead you client Id and secret can be passed during authenticaiton call, Like we have in Oauth 2.0 framework. Rest https calls should be made from client, So to avoid tampering of request, You can also go for mutual SSL between your client application and Zuul API gateway, It assures that call is coming from Desktop client only.
Yes, Zuul api gateway should be single entry point to your application, Your internal microservices should not be exposed to public.
For user registeration, Client authentication can be achieved using client Id and secret
Correct, You can also create http only cookie at backend, which will include your jwt token only.
Token refresh can be achieved at zuul api gateway, if session is active, make call to refresh token endpoint to get new access token.
On server side, At zuul proxy you can validate the incoming bearer token expiry along with signature validation, with generic claims too. Now at microservices level spring security can be used for role based access control for particular methods.
So we have an authentication server where the UI application gets the access token and then it communicate with API server, it's all good. Now we are building a third application which needs SSO to authenticate the same user and that is fine too.
However, there are scenarios where this third application needs to use some resources on the API server which, from my understanding, we need to get a token from auth server using client-id/secret and then send the request with the access token. This seems ok too, however I am not sure how API server is going to authorise that token (a hint on this would be great).
But the main problem is we want this request to be sent on behalf of the user. This is because API server needs to audit all user's activities. How can we achieve this using Spring Boot/OAuth2 and JWT Token?
I went through documentation and I know about #EnableOauth2Sso #EnableAuthorisationServer etc. but this scenario is not clear and I'm not even sure it's been implemented in Spring or not.
If there is no implementation for this scenario, what do you recommend? Any experience you have had on this, can you please share?
Your API server plays the role of a Resource Server. There is an annotation designed for that purpose: #EnableResourceServer. Your client app then will consume this resource using the handy OAuth2RestTemplate.
There are two approaches to properly configure the Resource Server and get this working:
Have the public key directly in your resource server app: this way when the client app try to use a token provided by the authorization server to get a resource from the Resource Server, this will verify if the token is valid by itself.
Configure the resource server to ask the authorization server if a given access token is valid and depending of the response it will allow or decline to get the resource.
I have posted a sample app on github using the first approach. There you can see the interaction between the Authorization Server, the Client and the Resource Server, as well as all the configurations you need for this implementation. Hope it helps you.
So I currently have this POC that I'm tinkering right now. I was thinking if it was possible that I can implement a Spring oAuth2 with JWT with a Authorization Server and a Resource Server both in different projects?
Flow goes like this User gets a token or passes through the Authorization Server and as long as he has the token and it's not expired he can make requests on the resource server.
I think that is the usual way to implement that. You have one authorization service providing tokens, either itself is backed by a database containing user information or maybe is asking another user service if the credentials are valid. The returned tokens can be used to make authorized request against the resource service(s).
Maybe take a look at the grant flow here.