I am implementing a login process using Spring Security + Spring session to build login functionality for a REST like backend service that needs to create/mantain a session.
I am not sure if I am approaching the solution the right way since I am using a custom endpoint to create the session manually. Maybe the session creation needs to be done in the Authorization method itself? Or maybe there is a way to have spring create the session after some request validations in the backend? I am using a custom filter and provider for this.
Also with my current configuration, I am having an issue since the backend API is creating a new session with every request, even when it should return 401.
The requirements of this solution is as follows:
- The clients will login to a third party authentication/authorization provider. Once validated, the provider will issue an access token.
- The API must validate the client's access token with the third party provider. Once validated, the API must create a session and return a new token (or sessionID) to the clients.
- Future calls to the API should include the token (or sessionID) in the header/cookie so the API gets the session of the client.
The big question here is: Is there a common approach to follow for using token based authentication linked to a user session? If so, what if I need to do custom validations before having spring session create the session, and also add custom attributes to this session?
My code is located here: https://github.com/munilvc/api-session/tree/master/src/main/java/com/munilvc/poc/security
For instance, some sample executions:
1) Execute custom login:
$ curl -X POST http://localhost:8080/app-api/login/createsession -v
> POST /app-api/login/createsession HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.49.1
> Accept: */*
>
< HTTP/1.1 200
< x-auth-token: 15a06ce8-5b34-401a-a05f-a0d933926245
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Tue, 29 Aug 2017 01:28:24 GMT
<
171{"username":"username1"}
2) Call another endpoint with provided x-auth-token:
NOTE the x-auth-token is refreshed in the response. (means a new session is created - This is what we want to avoid, this also happens when response is 401)
$ curl -X GET http://localhost:8080/app-api/accounts/2 -H "x-auth-token:15a06ce8-5b34-401a-a05f-a0d933926245" -v
> GET /app-api/accounts/2 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.49.1
> Accept: */*
> x-auth-token:15a06ce8-5b34-401a-a05f-a0d933926245
>
< HTTP/1.1 200
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< x-auth-token: 42a5db80-e5e1-4127-bd85-e468af4a8fb2
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Tue, 29 Aug 2017 01:29:08 GMT
<
870{"id":3,"name":"Account 3"}
PS: I am not sure if I am allowed to provide a link to the code in stack overflow. If not, I can paste the code here as well.
Thank you very much!
Based on your requirements, OpenID Connect can be used to authenticate the end-user and authorize a client which will then receive an
AccessToken
. Then theAccessToken
may be used to call the back-end API's (Resource Servers).Take a look at this sample/guide on how to setup login within Spring Security 5 against an external OAuth 2.0 or OpenID Connect provider. This will meet your requirement for logging into the application using an external provider and creating a secure session within Spring Security.
Now that you are logged in to the application and the client has an
AccessToken
, the client can use thatAccessToken
in the request (Authorization Header) to call the back-end API's (Resource Servers). The Resource Server should be setup to validate the incomingAccessToken
. Take a look at this sample (master and jwt-support branches) on how to configure a Resource Server.I would strongly recommend becoming more familiar with OAuth 2.0 Authorization Framework and OpenID Connect Core 1.0.
Good luck!