By: Troy Hart user 21 Feb 2017 at 2:50 p.m. CST

14 Responses
Troy Hart gravatar
I have built a simple spring boot client application that implements OAuth2 SSO. It almost works, but it fails executing the userinfo endpoint. I'm not getting any logging from GLUU, but I have some logging in my application: ``` 2017-02-21 13:35:10.212 DEBUG 30827 --- [nio-8080-exec-3] s.n.www.protocol.http.HttpURLConnection : sun.net.www.MessageHeader@4b645a705 pairs: {GET /oxauth/seam/resource/restv1/oxauth/userinfo?access_token=d267f621-63ee-407d-859a-b417d78cf22f HTTP/1.1: null}{Accept: application/json}{User-Agent: Java/1.8.0_101}{Host: troyh.dev.lan}{Connection: keep-alive} 2017-02-21 13:35:10.245 DEBUG 30827 --- [nio-8080-exec-3] s.n.www.protocol.http.HttpURLConnection : sun.net.www.MessageHeader@726cae8512 pairs: {null: HTTP/1.1 406 No match for accept header}{Date: Tue, 21 Feb 2017 20:35:10 GMT}{Server: Jetty(9.3.15.v20161220)}{X-Frame-Options: SAMEORIGIN}{X-Xss-Protection: 1; mode=block}{X-Content-Type-Options: nosniff}{Strict-Transport-Security: max-age=31536000; includeSubDomains}{Cache-Control: must-revalidate,no-cache,no-store}{Content-Length: 0}{Set-Cookie: JSESSIONID=1ueqvdio8flf1pmuimpkl8k0g;Path=/oxauth;Secure;HttpOnly}{Access-Control-Allow-Origin: *}{Connection: close} ``` Since my application is very simple, I'll include the code below: Boot application: ``` package com.nwri.explore.gluu.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DemoAppApplication { public static void main(String[] args) { SpringApplication.run(DemoAppApplication.class, args); } } ``` Java Configuration: ``` package com.nwri.explore.gluu.demo.config; import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration @EnableOAuth2Sso public class Oauth2Sso extends WebSecurityConfigurerAdapter { } ``` ``` package com.nwri.explore.gluu.demo.config; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; @EnableResourceServer public class ResourcesServer extends ResourceServerConfigurerAdapter { } ``` ``` package com.nwri.explore.gluu.demo.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class WebMvc extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("index"); registry.addViewController("/home").setViewName("home"); } } ``` Rest Controller: ``` package com.nwri.explore.gluu.demo.rest import java.security.Principal; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController public class User { @RequestMapping(method = RequestMethod.GET, path = "/user") public Principal userPrincipal(Principal user) { return user; } } ``` Application properties (yml): ``` logging.level.root: trace logging.level.org.apache.tomcat.util.net.NioEndpoint: info server: port: 8080 context-path: / spring: application: version: '@project.version@' security: oauth2: client: client-id: "@!EA31.F42A.1A30.8B32!0001!CBF6.3E76!0008!37FE.127E.E48A.8C04" client-secret: supersecret access-token-uri: https://troyh.dev.lan/oxauth/seam/resource/restv1/oxauth/token user-authorization-uri: https://troyh.dev.lan/oxauth/seam/resource/restv1/oxauth/authorize authentication-scheme: form #client-authentication-scheme: form scope: openid, profile, mobile_phone, uma_protection, email, permission, uma_authorization, phone, address, user_name, clientinfo resource: user-info-uri: https://troyh.dev.lan/oxauth/seam/resource/restv1/oxauth/userinfo ``` I'm still a little new to OAuth2 and spring boot. I can't figure out what I need to do.

By Aliaksandr Samuseu staff 21 Feb 2017 at 3:12 p.m. CST

Aliaksandr Samuseu gravatar
Hi, Troy. Unfortunately, we are now limiting free community support to list of RP implementations you can find [here](https://www.gluu.org/blog/limiting-openid-connect-community-client-support/). You are advised to first use any of those for your first experiments with OIDC (if you are new to it). After you've got a working setup with a supported RP app, you can monitor what is being sent back and forth during OIDC flows in it, and compare it with what your own code sends, this may give you some hints. Given the security implications of getting the API implementation correct, we strongly encourage you to use our commercial OAuth 2.0 client software: [oxd](http://oxd.gluu.org). There are libraries for all popular programming language, and we can provide better end-to-end support if we know both the client and server software.

By Troy Hart user 21 Feb 2017 at 4:56 p.m. CST

Troy Hart gravatar
I just had a call with Mike Schwartz a couple weeks ago and he said he was interested in supporting Spring, since so many people use it. So here I've provided you with all the source for a simple spring boot application (there's literally no business logic it's simple declaration of the spring library components) and I'm a little disappointed to hear that you have no interest in looking at it. I'm trying to build a case for recommending GLUU to my boss who will buy a support contract. The application I have shared here does work when I provide the endpoint properties for github as the OP: ``` oauth2: client: client-id: bd1c0a783ccdd1c9b9e4 client-secret: 1a9030fbca47a5b2c28e92f19050bb77824b5ad1 access-token-uri: https://github.com/login/oauth/access_token user-authorization-uri: https://github.com/login/oauth/authorize resource: user-info-uri: https://api.github.com/user ``` So, I must be very close. Also, I've read all the GLUU server OAuth2 and OpenID connect documentation I can find but can't figure out what the issue is. I will double back and read the documentation linked to in https://www.gluu.org/blog/limiting-openid-connect-community-client-support/ but there must be some way I can engage you to provide a little support here. No?

By Aliaksandr Samuseu staff 21 Feb 2017 at 5:05 p.m. CST

Aliaksandr Samuseu gravatar
If Michael thinks it may benefit Gluu, it's a different matter, of course. Then we should probably wait for his input on this.

By Michael Schwartz Account Admin 22 Feb 2017 at 2:42 p.m. CST

Michael Schwartz gravatar
We can support you if you use oxd. Assigning to Eugene who worked on the Spring oxd demo.

By Troy Hart user 22 Feb 2017 at 3:25 p.m. CST

Troy Hart gravatar
I don't want to use oxd because it doesn't seem to integrate well with spring security, especially when compared to spring-cloud-security where the integration with OAuth2 is purely declarative. Look at the code in this post. That is all the source required for a working OAuth2 SSO client demo application. The code doesn't work when I configure the OAuth2 endpoints for my GLUU server instance, but it does work when configured for github (see the configuration for github from my follow up above, it's just the endpoints...). The error I'm getting with GLUU happens after authentication, after the "code" is exchanged for an "access_token", when the client attempts to access the userinfo endpoint -- apparently GLUU doesn't like the Accept header (which you can see from the logs is: "Accept: application/json"). From what I can tell, spring-cloud-security provides all the same benefits you will argue oxd provides, plus it wraps it all up in spring security, enabling all the features that come with it. Now, I'm sure I could create an implementation around oxd that integrates with spring security, but it requires much more effort.

By Michael Schwartz Account Admin 22 Feb 2017 at 3:30 p.m. CST

Michael Schwartz gravatar
Your code is so simple because you're not using any of the security advantages of OpenID Connect. Are you validating the `id_token`? Are you checking that the state you posted in your request is returned unchanged? See the [attached screenshot](https://drive.google.com/open?id=0B2HQ7sefD4u9MkpuamF0QTZVaTg). Is it ok to be on the bottom rung of the security table?

By Troy Hart user 22 Feb 2017 at 3:44 p.m. CST

Troy Hart gravatar
Just because my implementation isn't handling the validation doesn't mean it's not happening. This declarative implementation pulls in spring's implementation of OAuth2, which does check the state for certain. As far as everything else it does or does not do, I'm not certain. However, I am certain that the spring team has the expertise to get the implementation right. Just like your team that builds oxd.

By Troy Hart user 22 Feb 2017 at 3:53 p.m. CST

Troy Hart gravatar
I'm not absolutely opposed to using oxd, but it doesn't seem very appealing for a couple reasons: - I must install and manage another server process - I have to implement integration with spring security and the extent of that integration code is an unknown.

By William Lowe user 22 Feb 2017 at 4:15 p.m. CST

William Lowe gravatar
Hi Troy, Yes, you do have to install and manage another process. But over the long term, it becomes hard to do end-to-end support when we have the server but not the client. That's why it's worth the extra work to run the oxd service, not unlike in Shib SP where you run the shibd service. Regarding your second point, you do not have to implement integration with spring security because we already do that in the [oxd spring library](https://oxd.gluu.org/docs/2.4.4/framework/spring/). These docs look a little light though, we're going to touch them up ASAP. Let's also see what Gene has to say, the developer who wrote the oxd spring library. Thanks, Will

By Michael Schwartz Account Admin 22 Feb 2017 at 6:02 p.m. CST

Michael Schwartz gravatar
Show me in the Spring code where it validates the id_token... [See Basic Implementer's Guide](http://openid.net/specs/openid-connect-basic-1_0.html#IDTokenValidation) I don't remember your application, but if security is important, you'll want to use OpenID Connect, not generic OAuth2. Also, are there other apps in your organization besides Spring? Or is there only one app, and it's a Spring app?

By Eugeniu Parvan user 24 Feb 2017 at 11:06 a.m. CST

Eugeniu Parvan gravatar
Hi Troy, I’ve played a bit with spring-social and created an [example project](https://github.com/worm333/spring-social-gluu) which connects to the Gluu server and retrieves user info. To test it you will need to: - replace [clientId](https://github.com/worm333/spring-social-gluu/blob/master/src/main/resources/application.yml#L11), [clientSecret](https://github.com/worm333/spring-social-gluu/blob/master/src/main/resources/application.yml#L12), [accessTokenUri](https://github.com/worm333/spring-social-gluu/blob/master/src/main/resources/application.yml#L13), [userAuthorizationUri](https://github.com/worm333/spring-social-gluu/blob/master/src/main/resources/application.yml#L14), [userInfoUri](https://github.com/worm333/spring-social-gluu/blob/master/src/main/resources/application.yml#L20) with yours. - make sure your client contains these scopes: `openid` and `profile` and response types contains: `code`. - add this login redirect uri to your client: `https://127.0.0.1:8443/login` - launch the app and point browser to: `https://127.0.0.1:8443` How it works. To get it work I had to override: - [AuthorizationCodeAccessTokenProvider](http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.html) with [GluuAuthorizationCodeAccessTokenProvider](https://github.com/worm333/spring-social-gluu/blob/master/src/main/java/com/example/GluuAuthorizationCodeAccessTokenProvider.java) because Gluu token_endpoint: `/oxauth/seam/resource/restv1/oxauth/token` requires `Authorization` header. - [UserInfoTokenServices](http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/security/oauth2/resource/UserInfoTokenServices.html) with [GluuUserInfoTokenService](https://github.com/worm333/spring-social-gluu/blob/master/src/main/java/com/example/GluuUserInfoTokenService.java) because of conflict between old and new jackson libraries(Gluu uses `org.codehaus.jackson`, while spring uses `org.fasterxml.jackson`), that provokes `org.springframework.web.client.HttpClientErrorException: 406 No match for accept header` error. Update. As I learned from Mike, there is no need to override [AuthorizationCodeAccessTokenProvider](http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/client/token/grant/code/AuthorizationCodeAccessTokenProvider.html), enough to make sure that authentication method for the token endpoint (in client configuration) is set to: `client_secret_post`. I've updated the example project. Regards, Eugeniu

By Michael Schwartz Account Admin 24 Feb 2017 at 12:03 p.m. CST

Michael Schwartz gravatar
Even though you can configure the Gluu Server like a generic OAuth 2 server, doesn't mean it's a good idea. The client library here is still not validating the `id_token`. I'm going to assign one of our engineers to write an oxd plugin for Spring Social...

By William Lowe user 23 Mar 2017 at 2:05 p.m. CDT

William Lowe gravatar
Troy, Did you ever get your SSO implementation working? Thanks, Will

By Troy Hart user 09 Apr 2017 at 12:52 p.m. CDT

Troy Hart gravatar
Thanks for checking back. I've been pulled off onto other tasks and haven't gotten back to this yet. I hope to pick it up again shortly and will be checking out the sample project Eugeniu put together. Thanks!