How to recover from a Spring Social ExpiredAuthorizationException - spring

I am trying to implement Google Oauth2 with Spring Social and spring-social-google. Initial authentication works fine. However after some time the authentication expires and I am hit by
org.springframework.social.ExpiredAuthorizationException: The authorization has expired.
How can you recover from this exception? Is it possible to somehow refresh the authorization?

Try to send additional access_type=offline paramter during authorization. It may looks something like this:
<form ...>
.....
<input type="hidden" name="access_type" value="offline"/>
</form>
Normally in this case authorization will be refreshed automatically for you. See this entry for more details.

Related

Automatic OpenId access token refresh on expiration

I'm trying to figure it out if OpenLiberty (Relying party impl) is able to automatically refresh the OpenId access token once it is expired by calling the token endpoint with the refresh token? I had a look at the code and I can't find any code indicating that it is doing this. Did I miss something?
Thanks for your help.
You are correct that the auto refresh of accessTokens using the refreshTokens is not supported in Liberty. You can open an issue.
--Ajay
This issue is now open in Open Liberty for this:
https://github.com/OpenLiberty/open-liberty/issues/15968
Are you looking for this support for the implicit flow with a browser-based SPA app or a basic/authentication flow (RP to OP)?
Liberty does not automatically refresh access_token with refresh_token. However, there is an option to ensure access_token is always valid whenever browser is refreshed. The way it works is like this: Liberty set browser security session time to be the lesser of id_token life time and access_token, and redirect user to OP for login if session expires. To do this, you set following properties: disableLtpaCookie ="true", reAuthnOnAccessTokenExpire="true", and optional property reAuthnCushion=.

Why need for redirect uri when requesting OAuth access token from Google?

I am trying to request an access token from Google do I can access a Google Drive account, to upload files.
I can make a an Auth request ...
<form method="POST" action="https://accounts.google.com/o/oauth2/auth">
<input type="hidden" name="scope" value="[YOUR SCOPE]"/>
<input type="hidden" name="client_id" value="[YOUR CLIENT ID]"/>
<input type="hidden" name="response_type" value="code"/>
<input type="hidden" name="redirect_uri" value="[YOUR RETURN URL]"/>
<input type="hidden" name="access_type" value="offline"/>
<input type="submit"/>
</form>
Why do I need the redirect_uri if I am making an HTTP request to obtain the access token. Wouldn't the token be returned within the response body?
My app does not involve any user interaction so I am not sure why a redirect is even necessary. I don't wish to use an SDK or library, rather I would just like to use HTTP via Postman.
My app does not involve any user interaction
Oauth2 does require user interaction to authenticate to a users account then your going to have to request access from them. A consent screen is displayed and the code is returned to the redirect uri
back to the basics of form submit ( without javascript), the form data will be sent to the uri you set in the action and the page will be redirected to what the server set it to, or page gets "reloaded" with a page that shows the response od the server.
I never tried Google OAuth2, but in general for this case, usually if your form submit is successful, it will redirect to your redirect_uri with the token appended on the uri as hash.
just realized u are using code grant type. so the flow is after this form submit, it will get redirected to Google IDM to authenticate and accpt consent, then redirect to redirect_uri with the auth code appended. then u can get the token by requesting it from the token endpoint with the code you obtained.

Client, Auth Server and Logout

So, i have a standalone OAuth2 auth server and client app (web-based), all using Spring OAuth2.
I have a login form host on the Auth server with redirection etc from the client app using Spring setup (via the login form).
All good so far.
I added a logout setup on the client:
.and()
.logout()
.addLogoutHandler(oauth2LogoutHandler())
.logoutSuccessUrl("/")
.clearAuthentication(true)
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
.permitAll()
That all 'seems' to be fine.
However, if i then hit the 'login' link on my client, when it redirects to the Authorisation app i dont get the login screen, but simply the redirection handshake occurs and i'm back in the client app.
So, the question is, what is it need to 'clear' in the Auth server when i logout on the client app? Somehow session info is persisting on the auth app but i cant find how that session is being picked up when i hit login? is there a clean way to propagate a 'logout' to the Auth Server?
Many Thanks
Martin
https://spring.io/blog/2015/02/03/sso-with-oauth2-angular-js-and-spring-security-part-v#the-logout-experience describes essentially the same problem for a notoriously tricky problem.
The Logout Experience
If you click on the “logout” link you will see that the home page changes (the greeting is no longer displayed) so the user is no longer authenticated with the UI server. Click back on “login” though and you actually don’t need to go back through the authentication and approval cycle in the authorization server (because you haven’t logged out of that). Opinions will be divided as to whether that is a desirable user experience, and it’s a notoriously tricky problem (Single Sign Out: Science Direct article and Shibboleth docs). The ideal user experience might not be technically feasible, and you also have to be suspicious sometimes that users really want what they say they want. “I want ‘logout’ to log me out” sounds simple enough, but the obvious response is, “Logged out of what? Do you want to be logged out of all the systems controlled by this SSO server, or just the one that you clicked the ‘logout’ link in?” We don’t have room to discuss this topic more broadly here but it does deserve more attention. If you are interested then there is some discussion of the principles and some (fairly unappetising) ideas about implementations in the Open ID Connect specification.
Here's a PR I submitted on github for an Spring-based OpenID Connect (an extention of OAuth2) project to implement an "End Session Endpoint" on the Authorization Server: https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server/pull/972. It implements part of the https://openid.net/specs/openid-connect-session-1_0.html#RPLogout spec for RP-initiated (or client-initiated) logout.
I don't think Spring has a built-in mechanism for this. There are other specifications, other than the one I partially implemented, for logout. Whichever you chose, it's probably a good idea to follow a documented spec.
You should enable the logout extending the WebSecurityConfigurerAdapter and create a logout page that send a post to /logout in the Authorization App
Logout page: (resources/templates/logout.ftl)
<html>
<head>
<title>Logout Page</title>
</head>
<body>
<form role="form" action="logout" method="post">
Logout
<input type="hidden" id="csrf_token" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<input type="hidden" id="redirect" name="redirect" value="${RequestParameters['redirect']!'/login'}"/>
<button type="submit">Logout</button>
</form>
</html>
The redirect input hidden will redirect to the client application after logout

Linkedin "Scope" Variable not set

I'm having trouble setting up a connection to Linkedin Api using Spring Social.
I am passing the "scope" variable "r_emailaddress" as a hidden field with the form to retrieve the email address but it's not working - I don't see the email_address permission like you do here. https://developer.linkedin.com/sites/default/files/gp-dialog.png
I am following the Spring Social Showcase Application Example. I should add, the Social Application there is no hidden scope field.
It works fine with Facebook.
Form
<form name="linkedinin_signin" id="linkedin_signin" action="${linkedin_uri}" method="POST">
<input type="hidden" name="scope" value="r_basicprofile, r_emailaddress" />
<input type="image" src="${linkedin_img_uri}" />
</form>
It is correct that LinkedIn is an OAuth 1.0a provider and that the "scope" parameter is non-standard with regard to OAuth 1.0(a). Therefore, Spring Social did not recognize the scope parameter for OAuth 1.0(a) providers.
However, you may be interested to know that yesterday I pushed a change to Spring Social that will allow any arbitrary parameter to be passed along to the request token URL and the authorization URL...including the "scope" parameter. This change, being relatively new, is only available in the latest 1.1.0.BUILD-SNAPSHOT builds, but will soon make an appearance in 1.1.0.M2. This should address your need.
You may also want to look at the Spring Social Showcase example, as it now uses the "scope" parameter to request "r_emailaddress" scope when a user connects to LinkedIn.
I'd appreciate any feedback you have on this change, preferably as comments to https://jira.springsource.org/browse/SOCIAL-349 or in the Spring Social forum at http://forum.springsource.org/forumdisplay.php?82-Social. (I do not monitor questions on StackOverflow nearly as often as I do on the Spring Social forum.)
I've had the same issue with LinkedIn. Here is what I did to resolve it:
instead of
final OAuth1Parameters params = new OAuth1Parameters();
params.set("scope", "r_emailaddress r_basicprofile");
I had to send a map with the fetchRequestToken
final MultiValueMap<String, String> mvm = new LinkedMultiValueMap<String, String>();
mvm.add("scope", "r_emailaddress");
mvm.add("scope", "r_basicprofile");
inRequestToken = oauth1Operations.fetchRequestToken(redirectUri, mvm);
LinkedIn is recognized by SpringSecurity as OAuth1 provider. OAuth1 does not support "Access Token Scope" feature. So your scope parameter is silently ignored. Actually LinkedIn uses non official OAuth 1.0a protocol version that has support for scopes. As a workaround you can try to override some SpringSocial classes and send scope parameter to LinkedIn. See this thread.
The oAuth1 API of linked in doesn't support the scope parameters at all, you must use oAuth2 - http://developer.linkedin.com/documents/authentication - to be able to get the email address

Requestign addional permission to linkedin via ProviderSigninController

I'm using spring social to login using linked-in, I need to request for additional permission, I do with scope variable for other providers (facebook, twitter) it just works fine but for linked-in it does not, since Linked-in uses oAuth 1.0 it's not supported - is what I could see in other forums, I'm sure there is a work around could you suggest one ?
<form id="linkedin-login" action="signin/linkedin" method="POST">
<input type="hidden" name="scope" value="r_fullprofile" />
</form>
Thanks in adavance.
Hi I'm answering back to my own question, that might be some help to others as well.
Linkedin uses OAuth 1.0a. OAuth1.0 officially does not support scoping of authorization, It's only Linkedin extension to OAuth1.0, since Spring social follows the standard of OAuth1.0, the scoping does not come out of the box, it needs a work around of overriding / adding new ProviderSigninController, connect controller and Connectsupport (getAccessToken method) classes.
More details: http://forum.springsource.org/showthread.php?129684-Linked-In-member-permissions

Resources