Springboot OIDC refresh token after expiration - spring

Im facing a problem which I cannot solve by myself.
I am using Spring Boot and Spring's spring-boot-starter-oauth2-client to connect to my IDP.
I configured my settings and when the User hits a #Secured endpoint, one gets redirected to the IDP's login form.
After successful login the User becomes redirected to the initial request and is now logged in.
This is all working fine until the requested token expires.
Now I was wondering if I can refresh the Token using the refresh token ?
Is there a way to do that ?
Thanks for any help.
Detlef

Related

Keycloak not logging out the Identity provider after calling the /logout endpoint

I'm trying to use Keycloak (13.0.1) as an identity broker. I have an iOS app that uses keycloak to log in via an OIDC identity provider, and then use the token to access a spring-boot backend.
My issue is that I simply can't get the keycloak logout to also log the user out of the Identity Provider session.
I've spent days googling this and looking at both stackoverflow and the keycloak discourse page and git repo, but I couldn't find an answer to my specific issue.
Using the postman to test, the first time I click "Get New Access Token":
It successfully redirects me to the identity provider login page (I use the keycloak hint to bypass the initial keycloak login page). Pressing the button again will skip the IDP login and give me the token directly. How convenient, or so I thought...
The problem is that when I use keycloak's /logout endpoint to invalidate the refresh token:
And it successfully returns 204, when I click "Get new access token" again, it skips the login form and gives me the token directly, so there is effectively no way to logout the user and then login with a different user. The only way to bypass this is to manually click the "clear all cookies" button.
Here is my IDP configuration:
Also note that, in the keycloak admin guied it is specified that keycloak should be logging out of the IDPs when a logout is triggered, so it doesn't seem like I should be making any special configs:
https://www.keycloak.org/docs/latest/server_admin/#identity-broker-logout
IMPORTANT EDIT:
I marked this question as solved and the solution is correct, but I also needed to turn off the IDP "backchannel logout", because our corporate SSO doesn't like it. Keycloak seems to be able to log out regardless.
It successfully redirects me to the identity provider login page
That redirect is the key. It opens a browser, where Keycloak cookie is created - that is your IdP session. You have to open Keycloak /logout endpoint in the same browser, so Keycloak can clear own Keycloak cookies.
Summary: you have to open/redirect (API call doesn't work) user to the same browser to the logout endpoint (API call doesn't work) as you have used for the login. Of course this may not be case for some special flows, but it should be working for standard Authorization Code (with/without PKCE).

Spring Security 5 does not seem to handle OAuth2 access token expirations - asks the user to login again

I am reading the tutorial at https://spring.io/guides/tutorials/spring-boot-oauth2/ on how to create an Oauth2 login page and using a client to access protected resources. The source for that tutorial is on github.
But the tutorial doesn´t seem to handle the situation when the access token from Github is expired. When the access token has been expired I expect Spring Security to handle it so I can keep making requests to Github. But instead I have to login again to gain a new access token.
What do I need to do to get Spring Security to get a new access token from the refresh token when the access token has been expired?

Logout with Spring Security and Keycloak OpenID Connect doesn't work

I am maintaining this application which is set up with:
an AngularJS front end
a Spring back end (with Spring Security, configured as per the Keycloak documentation) running on Tomcat
Keycloak as single sign-on solution using OpenID Connect.
The Implicit Flow is implemented like this:
The user navigates to the web app in their browser
The AngularJS web app checks if a (non-expired) JWT token is present in the Session Storage
If not, it redirects to Keycloak to request a token
Keycloak authenticates the user and redirects back to the webapp with the token
The web app stores the token in the Session Storage
Any request the web app makes to the back end API, it inserts the header Authorization: Bearer <token>
So far, so good. However, I noticed that logging out does not work as expected:
The user clicks the logout button in the web app
The web app deletes the token from the Session Storage
The web app redirects to the Keycloak logout endpoint
The user accesses the back end API directly and succeeds!
The reason is that a JSESSIONID cookie is stored and this also authorizes the user to access the API.
My questions:
Why is a JSESSIONID cookie being created? Is it default behaviour of Spring Security? Or did I misconfigure something?
How should I fix the logout issue? Make sure a JSESSIONID cookie is never created? Or implement a logout endpoint in the backend that deletes the session cookie?
NB: I am aware of
the risks of storing credentials in Session Storage;
the Implicit Flow being deprecated.

Spring Security set CSRF in login response with new session token

I'm using spring security in my spring boot application. I have a front end single page app that logs in via rest. I have no problem logging in, but once I've logged in, my session token changes, BUT THE CSRF TOKEN DOES NOT.
Is there any way to force spring security to set the csrf token since the old token associated with the un-authenticated session token will not work with the new authenticated session token?
I'm storing the CSRF token in a cookie, and sending it back from the client in the header of every state altering request. I can't login and logout without an intervening request (non-post) to retrieve the csrf token. This seems like a crock.
SO a simple solution is to redirect the login request once it's successful. This puts the request through another loop through the security filter chain ensuring a new CSRF is added to the new session token. A good night sleep does wonders.

Issue token to logged in user via spring

I have a Spring (3.2) based web app that a user can log into. The site will also provide an API secured via OAuth 2.0. My question then, is how do I go about generating a token for a logged in user?
The underlying idea here is that there will be a mobile app that opens up a web frame to the login page, which will eventually redirect to a url schema with an oauth token that the app will catch and then use for the api calls. Looking at the code for TokenEndpoint, I see that it defers token creation to a list of TokenGranter types. Should I be creating my own TokenGranter extended class, or am I looking at this all wrong?
I ended up writing a controller like this:
OAuthClientRequest request = OAuthClientRequest
.authorizationLocation(csOauthAuthorizeUrl)
.setClientId(csClientId)
.setRedirectURI(
UrlLocator.getBaseUrlBuilder().addSubpath(AUTH_CODE_HANDLER_URL).asUnEscapedString())
.setResponseType("code")
.buildQueryMessage();
UrlUtils.temporarilyRedirect(httpResponse, request.getLocationUri());
return null;
Then handling the code returned. My big problem here was that I had the /oauth/authorize endpoint set to use client credentials. Once I realized that tokens were being issued for the client ID instead of the user, it started to make sense.
So you want to use the Authorization Flow of OAuth. Spring has already support that, if you have configured the spring-security-oauth correctly, you just have to redirect the user/your mobile apps to /oauth/authorize?client_id=xxx&response_type=code this will redirect user to authorization page, if user has not login yet, it will redirect the user to login page then to the authorization page.
After the user completed the authorization process, it will redirect the user to an already registered redirect_url parameter with the authorization_code 'yourapp.com/callback?code=xxxx'.
Your application should exchange this authorization_code with the real token access to /oauth/token?grant_type=authorization_code&code=xxxx&client_id=xxxx&client_secret=xxxx
After that you will receive the token access that can be used to access the resource server.

Resources