Spring-security: OAuth 2 Login Not Working With Linkedin

Created on 17 Oct 2018  路  4Comments  路  Source: spring-projects/spring-security

I am using Spring Boot 2.0.6-RELAESE
And following configuration for OAuth 2:
spring:
security:
oauth2:
client:
registration:
google:
client-id: @google.client-id@
client-secret: @google.client-secret@
facebook:
client-id: @facebook.client-id@
client-secret: @facebook.client-secret@
linkedin:
client-id: @linkedin.client-id@
client-secret: @linkedin.client-secret@
provider: linkedin
scope: r_basicprofile,r_emailaddress
client-authentication-method: post
authorization-grant-type: authorization_code
redirect-uri-template: http://localhost:8080/login/oauth2/code/linkedin
client-name: Linkedin

    provider:
      linkedin:
        authorization-uri: https://www.linkedin.com/oauth/v2/authorization
        token-uri: https://www.linkedin.com/oauth/v2/accessToken
        user-info-uri: https://api.linkedin.com/v2/me

Its failing inside NimbusAuthorizationCodeTokenResponseClient at Line 101:
tokenResponse = com.nimbusds.oauth2.sdk.TokenResponse.parse(httpRequest.send());
with Parse Exception showing stack trace on console:

com.nimbusds.oauth2.sdk.ParseException: Missing JSON object member with key "token_type"
at com.nimbusds.oauth2.sdk.util.JSONObjectUtils.getGeneric(JSONObjectUtils.java:127) ~[oauth2-oidc-sdk-5.64.4.jar:5.64.4]
at com.nimbusds.oauth2.sdk.util.JSONObjectUtils.getString(JSONObjectUtils.java:263) ~[oauth2-oidc-sdk-5.64.4.jar:5.64.4]
at com.nimbusds.oauth2.sdk.token.BearerAccessToken.parse(BearerAccessToken.java:187) ~[oauth2-oidc-sdk-5.64.4.jar:5.64.4]
at com.nimbusds.oauth2.sdk.token.AccessToken.parse(AccessToken.java:273) ~[oauth2-oidc-sdk-5.64.4.jar:5.64.4]
at com.nimbusds.oauth2.sdk.token.Tokens.parse(Tokens.java:167) ~[oauth2-oidc-sdk-5.64.4.jar:5.64.4]
at com.nimbusds.oauth2.sdk.AccessTokenResponse.parse(AccessTokenResponse.java:199) ~[oauth2-oidc-sdk-5.64.4.jar:5.64.4]
at com.nimbusds.oauth2.sdk.AccessTokenResponse.parse(AccessTokenResponse.java:236) ~[oauth2-oidc-sdk-5.64.4.jar:5.64.4]
at com.nimbusds.oauth2.sdk.TokenResponse.parse(TokenResponse.java:95) ~[oauth2-oidc-sdk-5.64.4.jar:5.64.4]
at org.springframework.security.oauth2.client.endpoint.NimbusAuthorizationCodeTokenResponseClient.getTokenResponse(NimbusAuthorizationCodeTokenResponseClient.java:101) ~[spring-security-oauth2-client-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.security.oauth2.client.endpoint.NimbusAuthorizationCodeTokenResponseClient.getTokenResponse(NimbusAuthorizationCodeTokenResponseClient.java:67) ~[spring-security-oauth2-client-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationProvider.authenticate(OAuth2LoginAuthenticationProvider.java:121) ~[spring-security-oauth2-client-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174) ~[spring-security-core-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter.attemptAuthentication(OAuth2LoginAuthenticationFilter.java:166) ~[spring-security-oauth2-client-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) ~[spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter.doFilterInternal(OAuth2AuthorizationRequestRedirectFilter.java:129) [spring-security-oauth2-client-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.10.RELEASE.jar:5.0.10.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) [spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66) [spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.10.RELEASE.jar:5.0.10.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.0.9.RELEASE.jar:5.0.9.RELEASE]

The stack trace shows response for accesstoken not contain key "token_type", so its failing.
But when I hit access token request with Postman at URL:

https://www.linkedin.com/oauth/v2/accessToken?code=code&client_secret=client_secret&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Flogin%2Foauth2%2Fcode%2Flinkedin&client_id=client_id
I am getting the access token in format below:
{
"access_token": "access_token",
"expires_in": 5183999
}

How we can fix it??

oauth2

Most helpful comment

@ankurpathak We are aware of this issue with LinkedIn and oauth2Login() in Spring Security 5.0.

As an FYI, the token_type parameter is required as per spec.

token_type
REQUIRED. The type of the token issued as described in
Section 7.1. Value is case insensitive.

In the recent 5.1 release, you are now able to customize the handling of the Token Response by configuring a custom Converter<Map<String, String>, OAuth2AccessTokenResponse>.

Please see the recent reference doc on OAuth2AccessTokenResponseClient.

Also, take a look at this sample configuration and custom Converter<Map<String, String>, OAuth2AccessTokenResponse> implementation. You will notice that CustomAccessTokenResponseConverter defaults OAuth2AccessTokenResponse.tokenType to OAuth2AccessToken.TokenType.BEARER, which will resolve the issue you are having with LinkedIn.

I'm going to close this issue as I feel I have provided you the solution to resolve. If not we can re-open and discuss further.

All 4 comments

@ankurpathak We are aware of this issue with LinkedIn and oauth2Login() in Spring Security 5.0.

As an FYI, the token_type parameter is required as per spec.

token_type
REQUIRED. The type of the token issued as described in
Section 7.1. Value is case insensitive.

In the recent 5.1 release, you are now able to customize the handling of the Token Response by configuring a custom Converter<Map<String, String>, OAuth2AccessTokenResponse>.

Please see the recent reference doc on OAuth2AccessTokenResponseClient.

Also, take a look at this sample configuration and custom Converter<Map<String, String>, OAuth2AccessTokenResponse> implementation. You will notice that CustomAccessTokenResponseConverter defaults OAuth2AccessTokenResponse.tokenType to OAuth2AccessToken.TokenType.BEARER, which will resolve the issue you are having with LinkedIn.

I'm going to close this issue as I feel I have provided you the solution to resolve. If not we can re-open and discuss further.

@jgrandja I got an Idea about this. But I am doing multiple provider Google, Facebook and Linkedin.
How I will make sure it will kick in for only Linkedin and notfor other providers facbook and google which
are just working fine.

@ankurpathak I put together a sample that has LinkedIn, Google and local UAA.

See the linkedin branch

@jgrandja Linkedin now works like a champ. Thanks.

Was this page helpful?
0 / 5 - 0 ratings