'Springboot + JWT +OAuth2 + AngularJS Stateless session

I am trying various Java Spring based security implementations as follows

1. JWT Authentication

  • User access /
  • Springboot identifies as protected resource and redirects user to /login
  • User enters credentials and browsers does a POST to /authenticate
  • Server validates the credentials and generates JWT token. Set into response header and redirects to /
  • Browser loads /. AngularJS recognizes JWT token in the response header and stores the same in the localStorage
  • All subsequent calls will have the Bearer token in header (injected through httpInterceptor)

Note: Stateless Session

2. OAuth2 authentication

  • User access /
  • Springboot identifies as protected resource and redirects user to /login
  • /login is intercepted by Spring security. Redirects to Oauth2 authorization server with a generated state and redirect URL back to application
  • User enters credentials
  • Oauth server redirects back to application URL "/login?code=xxx&state=yyy"
  • /login is intercepted by Spring security. Recognizes the code and state, generates Cookie and sets in response header. Redirects to /
  • Browser loads /. Browser recognizes cookie in the response header and stores the same.
  • If a call is made to /user, the Principal object is populated with the JWT which I am able to extract as follows
@RequestMapping(value= {"/user")
public ResponseEntity<Map<String, String>> user(Principal principal) throws Exception {
    OAuth2Authentication obj = (OAuth2Authentication) principal;
    authentication = obj.getUserAuthentication();
    OAuth2AuthenticationDetails oAuth2AuthenticationDetails = (OAuth2AuthenticationDetails) obj.getDetails();
    String jwt = oAuth2AuthenticationDetails.getTokenValue();
  • All subsequent calls will have the Cookie in the Request

Note: A Stateful Session is created in server side to store the session details. This required to decrypt the cookie and identify the user

Now I want to implement security using Oauth2+JWT but stateless at same time as follows

3. OAuth2 + JWT + Stateless

  • User access /
  • Springboot identifies as protected resource and redirects user to /login
  • /login is interecepted by Spring security. Redirects to Oauth2 authorization server with a generated state and redirect URL back to application
  • User enters credentials
  • Oauth server redirects back to application URL "/login?code=xxx&state=yyy"
  • /login is intercepted by Spring security. Recognizes the code and state, extract JWT token by invoking OAuth2AuthenticationDetails.getTokenValue() and set in response header. Redirect to /
  • Browser loads /. AngularJS recognizes JWT token in the response header and stores the same in the localStorage
  • All subsequent calls will have the Bearer token in header (injected through httpInterceptor)

Question

I am trying to figure out how to implement the highlighted step above



Solution 1:[1]

Just an idea/direction, if I got you right: You can create a GenericFilterBean and add that to the HttpSecurity filter chain.

When using JWT, there should be something similar (a filter, which extracts the bearer-token from the header) and then populates an Authentication object for Spring Security.

So the new filter could grab the token from the request and set the response accordingly. You could also handle that in an unprotected (!) callback endpoint like login/callback?..., which than sets the cookie for you.

In our application, the server (spring boot) is totally stateless and does not have any oauth nor stateful stuff. Obviously it never redirects anything or has any other views/endpoints than / for AngularJS (and some REST-APIs under /api/...). Thus, the OAuth-flow is totally handled by AngularJS, which in turn checks the callback from the oauth-server and locally sets the JWT-Token (like in your first approach). In first versions we also tried to mix up redirects with stateless JWT and stateful sessions etc., but this led to very strange behavior with the logins - the state (logged in or not) was not always clear and in some cases redirects were wrong etc.

Solution 2:[2]

This might help you implement your desired solution.

The author proposes that once a user successfully authenticates with Oauth2 providers (Google etc), you send a short-lived token as a URL param to your frontend application and use this short-lived token to exchange it for a longer-lived token.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Indivon
Solution 2 lisymcaydnlb