Spring Boot authorization using JWT - spring

Am I correct in the following thought process?
For a native app I'm building I want to implement a backend in Spring Boot.
This backend will be secured using Spring Security. Since I will manage and develop everything myself (the backend, the native app(s) and the web app for backend management) securing everything with JWT would be sufficient and implementing a full oauth server would be a bit overkill.
I have implemented the JWT token generation in my backend at this moment. On user sign in, the backend returns a json object containing some user details as well as an access token and a refresh token. The access token will be short lived, the refresh token will be long-lived (speaking about months of life time, maybe even indefinite unless revoked).
Is it correct that the refresh token could theoretically also be used as the access token? Or should I set some value/data in the refresh token that identifies it as a refresh token only (so can't be used to access resources, only to generate new access token)?

Related

Spring boot API with both Oauth 2.0/OpenID Connect and internal authentication?

I'm having a hard time figuring a good way to implement Oauth 2.0 and OpenID Connect authentication alongside an existing internal email+password authentication for a B2B Web app's API using Spring security.
We have a backend REST API that is a Spring Boot servlet application which currently authenticates users with OAuth 1.0 and the password grant. The front-end is an Angular single-page app through which users must log in with their username and password. The API's /oauth/token endpoint then delivers an opaque access token to be used for fetching secured resources that are then displayed within the app.
We'd like to add the possibility to log in using external authentication with OpenID connect, which is a perfect opportunity for switching to OAuth 2.0 and JWT tokens. Our API would then accept JWT tokens it delivered as well as external JWT tokens emitted by accepted issuers.
Reading and validating JWT tokens won't be a problem using Spring security's OAuth Resource Server. However things get complicated with how to make the classic username+password login flow work with JWT tokens.
We thought about delivering JWT access tokens the same way we used to with our old OAuth 1.0 tokens. The thing is, newer OAuth specifications advise against using the password grant, plus it simply isn't supported in the Spring authorization server project we're planning to use. The authorization-code flow w/ PKCE seems like too much for this case as we do not want the back-end API to render a login form but use credentials entered in the existing login form that is part of the single-page app.
I've read a lot about not using OAuth for 1st party login since its primary use is for external authentication, but again, that doesn't apply since we also want 3rd party authentication.
What would be a secure way to implement a Spring boot authorization server that can deliver JWT access tokens to a 1st party client in exchange for a user's credentials, all this using the existing log in page, and given the password grant type no longer being supported?
I thought about implementing a preliminary step that would be a POST request with Basic authentication to a /login endpoint that just returns a 200 HTTP status, then proceeding to the /oauth2/authorize request that would deliver the authorization code immediately without redirecting since my session is authenticated.
I'll be happy to provide more details if needed. Here are the resources I'm using for this project.
What about setting up an authorization-server capable of identity federation?
In such configuration, the authorization-server is responsible for providing with identities, proxying one or more sources (your existing user database for instance, plus maybe Google, Facebook, Github, etc.)
Keycloak does it for instance.
From the client point of view (your Angular app), the authorization-server is used to get:
access-token: put in Authorization header of requests to secured resource-server(s) (can be a JWT or an opaque string, doesn't matter, clients should not try to extract data from access-tokens)
refresh-token: send to authorization-server to renew access-token before it expires
id-token: get user-profile data (email, username, profile picture, etc.)
You should have a look at https://github.com/damienbod/angular-auth-oidc-client for connecting an Angular app to an OIDC authorization-server.
From resource-server point of view, access-tokens are the source ofr setting-up security-context, either by decoding and validating a JWT locally or with token introspection on authorization-server.
Have a look at those tutorials for such resource-servers configuration.

JWT with JDBC token store vs JSESSION ID

I have implemented a spring boot application which does authentication and authorization using Spring OAuth2.
I am using JDBC token store to main the token issued to the client for performing Custom claim verification and some other user status verification during application run-time.
The question is, since i had used traditional JSESSIONID with CSRF token, i cannot find any advantage with the new OAuth standards because after login i would store the user details in the session and retrieve it whenever needed similarly for OAuth i store the User details in the JWT token itself and decode the token every time to get the user information, also i need to hit the database anyway for custom claim verification such as JTI verification .
Everyone says JWT is for stateless application but with JDBC token store i'm holding all the token that is issued to each client. Also there is an additional overhead to purge the expired token which will be done automatically with Session. Also i'm using refresh token as the way to implement session timeout.
Therefore can anyone explain me, when should i use JSESSIONID and when to use JWT ? My application is running on AWS architecture.
From my experience, cookie-based authentication sufficiently complicates scaling and load-balancing. If you have authenticated via the first service replica, your cookie will be not appliable to another replica, cause all sessions are stored in memory. So, if you want to scale your service in the future, session-based authentication can make things much more complex.

How to horizontally scale a Spring Security OAuth2 Client?

Spring Security OAuth2 Client uses HttpSession to store the access token if we use oauth2Login() to obtain the access token from Okta (Authorization server). That will force us to have only a single instance of OAuth2 client and won't be able to horizontally scale in an environment like Kubernetes.
To solve this issue I was able to find different approaches on the internet.
Use implicit flow where the access token is obtained and maintained in the browser client which is less secure to the above approach.
Once you obtained the access token in the backend, produce a new custom JWT token with all the claims copied and store it in the user's browser. So every subsequent request can be authenticated using that JWT token thereafter.
Use the Spring-Session library to share the HttpSession between multiple OAuth2 client instances and stick to plain old HTTP sessions to store access token.
What would be a better approach?

What is the advantage of providing a Tokenized Authentication in an application with Spring Boot Backend over SecurityContextHolder?

I was getting started with Spring Boot and Angular 7 and I came across user authentication.
Let's assume the following: I have a frontend with Angular 7 and a Backend with Spring Boot that offers API's that can be accessed via HTTP.
So I know that usually the frontend authenticates the user with e.g. JWT that stores all necessary information about the user that might be needed. But I came across the SecurityContextHoler of Spring Boot Security:
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
This allows me to simply access granted Authorities and so on. So I thought about the following:
Using JWT for the frontend grants the following advantages (as far as I know):
* Users can identify when using API's
* Users may be prevented from certain UI-Elements (based on roles stored in JWT)
* Modification prevention due to checksum (invalid token afterwards)
Now I could also add a check in my Controller in the Backend that checks the SecurityContextHolder for user permission (something like a Service that checks the current context permissions vs the needed permission and returns true/false). Wouldn't that be even more save, since it is in the backend (so in my inmagination everything that runs server-sided is always a little more save than what runs client-sided)?
I can store information in the frontend (like roles and a username) to use them for the UI-based-access prevention to still have the same advantages as JWT provides, but I do not have the "effort" of implementing the JWT creation.
But obviously it is not common to do it that way (at least I never saw it), so what is the advantage of the Tokenization?
They are not mutually exclusive. You would use what you call "Tokenized Authentication", like an oAuth2 Bearer token most likely in a JWT when the Authentication is performed by a separate system from your Spring Boot backend. For example, you may be using Okta, Keycloak, Google or Facebook to authenticate the user.
At a minimum, your Spring Boot backend stores the username extracted from the JWT in the Authentication. You can get Spring Boot to extract any roles in the token and add those to Authentication::grantedAuthorites. If your backend system, has it's own set of roles in addition to what's in the token, then the backend could implement a PrincipalExtractor to load a UserDetails object for this user from the database as the Principal and merge the roles in the token with those store in the local database.
You'll probably want to security certain methods in your backend with method security annotations like #PreAuthorize(), since you shouldn't trust the front end. The method security will check permissions, like hasRole("ADMIN") or hasPermission(object, 'READ') using the Principal object in SecurityContextHolder.getContext().getAuthentication();
In the end, the token assures the backend the user accessing it is who they say they are, i.e. Authentication, but does not necessarily tell the backend what they are Authorized to do. Yes, if you control the Authentication server you can include roles in the JWT, but roles don't usually provide as fine a grained control as is required.
Independent of what level of security you implement, the token is translated into an Authorization so you can use the Spring Security framework to manage access within your backend code.
There are 3 type of token in spring security OAuth2:
1. InMemory token Store
2.JWT token store
3.JDBC token store
So now you’re talking the JWT token store. The most powerful of JWT token store is prevent the authorization server load against to the database for checking such as role,token expired so it is related database load performance. Since all the information such as: role,username, token expire ,etc include in token itself. So the authorization server or other resource sever may using the public key to verify this token itself without invoke to data store.
Hope helpful! ☺️

How to handle token expirations in a Spring OAuth SSO Authorization server?

I have been following a tutorial to create a Spring SSO application which uses Facebook for authentication but creates its own access tokens to secure back-end resources.
The sample application creates a user on first login and stores the user's facebook token for further use (getting data from facebook later on).
My question is that how do I handle token expirations? When the facebook token expires, how do we setup spring security to refresh it? What about our application's token expiration?
You can find my sample project here.
The app in the tutorial only uses the token for authentication (i.e. it uses it once when the user logs in to get the user's personal details), so it's highly unlikely to expire in the time it is being used. Having said that, the OAuth2RestOperations instance that is used to carry out that single request is capable of refreshing the token on its own (if the provider sent it a refresh token and allows the access token to be refreshed by your client).

Resources