Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authentication issue missing profile information #3

Closed
cpppwner opened this issue Jan 12, 2018 · 10 comments
Closed

Authentication issue missing profile information #3

cpppwner opened this issue Jan 12, 2018 · 10 comments
Labels
Milestone

Comments

@cpppwner
Copy link
Contributor

It seems there is an issue with retrieving profile related information when the OpenID Connect Provider is Jetbrains Hub (https://www.jetbrains.com/help/hub/OpenID-Connect.html).

In my setup, I am using

  • Hub 2017.4 which is the latest available version
  • SonarQube 6.7.1 LTS
  • sonar-auth-oidc plugin 1.0.1

After trying to login I get the following in my browser.
image

In the web.log file you'll find a stack trace at the end, saying
java.lang.IllegalArgumentException: User login must not be blank.

I set the sonar.log.level.web to DEBUG and attached the web.log file.
web.log

@tjuerge tjuerge added this to the 1.0.2 milestone Jan 12, 2018
@cpppwner
Copy link
Contributor Author

A pull request fixing this issue will come quite soon.

@tjuerge tjuerge added the bug label Jan 12, 2018
@tjuerge
Copy link
Contributor

tjuerge commented Jan 12, 2018

The attached web.log contains the following debug log:

2018.01.12 22:47:11 DEBUG web[AWDsVzxys4R6VWulAAAL][o.v.s.a.o.OidcClient] Authentication request URI: http://localhost:8080/hub/api/rest/oauth2/auth?response_type=code&client_id=60dcacaf-8a94-4177-b2f2-1348463f88ce&redirect_uri=http%3A%2F%2Flocalhost%3A9000%2Foauth2%2Fcallback%2Foidc&scope=openid+email+profile&state=9r0aetskjatck0110fmh2tr11k
2018.01.12 22:47:16 DEBUG web[AWDsVzxys4R6VWulAAAM][o.v.s.a.o.OidcClient] Retrieving authorization code from callback request's query parameters: code=4djOCyiV&state=9r0aetskjatck0110fmh2tr11k
2018.01.12 22:47:16 DEBUG web[AWDsVzxys4R6VWulAAAM][o.v.s.a.o.OidcClient] Authorization code: 4djOCyiV
2018.01.12 22:47:16 DEBUG web[AWDsVzxys4R6VWulAAAM][o.v.s.a.o.OidcClient] Retrieving OIDC tokens with user info claims set from http://localhost:8080/hub/api/rest/oauth2/token
2018.01.12 22:47:16 DEBUG web[AWDsVzxys4R6VWulAAAM][s.n.w.p.h.HttpURLConnection] sun.net.www.MessageHeader@2951d0bd8 pairs: {POST /hub/api/rest/oauth2/token HTTP/1.1: null}{Authorization: Basic NjBkY2FjYWYtOGE5NC00MTc3LWIyZjItMTM0ODQ2M2Y4OGNlOk1xNk1vd3JieThJQw==}{Content-Type: application/x-www-form-urlencoded; charset=UTF-8}{User-Agent: SonarQube 6.7.1.35068 # AWDsR0pnqfrgOxA26hDz Java/1.8.0_152}{Host: localhost:8080}{Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2}{Connection: keep-alive}{Content-Length: 113}
2018.01.12 22:47:16 DEBUG web[AWDsVzxys4R6VWulAAAM][s.n.w.p.h.HttpURLConnection] sun.net.www.MessageHeader@f99ea388 pairs: {null: HTTP/1.1 200 OK}{Date: Fri, 12 Jan 2018 21:47:16 GMT}{Content-Type: application/json;charset=utf-8}{Cache-Control: no-cache, no-store, no-transform, must-revalidate}{Vary: Hub-API-Version}{Vary: Accept-Encoding, User-Agent}{Content-Length: 731}{Server: Jetty(9.3.20.v20170531)}
2018.01.12 22:47:16 DEBUG web[AWDsVzxys4R6VWulAAAM][o.v.s.a.o.OidcClient] Token response content: {"id_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJzdWIiOiJlNjVjOTYwNy1mZDRlLTRiY2QtOTdiMS1jYTA1NzYxNjU5MGUiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvaHViIiwiYXVkIjpbIjYwZGNhY2FmLThhOTQtNDE3Ny1iMmYyLTEzNDg0NjNmODhjZSJdLCJleHAiOjEuNTIzNTY5NjM2MjFFOSwiaWF0IjoxLjUxNTc5MzYzNjI3OEU5LCJhdXRoX3RpbWUiOjEuNTE1NzkzNjM2MjFFOX0.HSObeExr6V5NvYvAsfXtadl4V4dr7c3iKWBgGS492b-EwJyOFxCRcKFk52TZ_KnwGYaLHbMOn4MOym_WKrrnKU4D9Fqb9bLXjngxVno5uJu-r9YCgmky8AgoGEmu_BkSvj5uWsRNbGGUwT-fS2CmR-tCI3GsWmTUsqw5FUCdFo0","access_token":"1515797236280.60dcacaf-8a94-4177-b2f2-1348463f88ce.e65c9607-fd4e-4bcd-97b1-ca057616590e.0-0-0-0-0;1.MCwCFFLOdhIbimizA3BP87j7768mScusAhR879tCoU0f80x3cdhQ8lfjIDjNDA==","token_type":"Bearer","expires_in":3600,"scope":"0-0-0-0-0"}

2018.01.12 22:47:16 DEBUG web[AWDsVzxys4R6VWulAAAM][o.v.s.a.o.OidcClient] User info: {"sub":"e65c9607-fd4e-4bcd-97b1-ca057616590e","aud":"60dcacaf-8a94-4177-b2f2-1348463f88ce","auth_time":1.51579363621E9,"iss":"http:\/\/localhost:8080\/hub","exp":1523569636,"iat":1515793636}
2018.01.12 22:47:16 ERROR web[AWDsVzxys4R6VWulAAAM][o.s.s.a.AuthenticationError] Fail to callback authentication with 'oidc'
java.lang.IllegalArgumentException: User login must not be blank
	at org.sonar.api.internal.google.common.base.Preconditions.checkArgument(Preconditions.java:122)
	at org.sonar.api.server.authentication.UserIdentity$Builder.validateLogin(UserIdentity.java:191)
	at org.sonar.api.server.authentication.UserIdentity$Builder.build(UserIdentity.java:179)
	at org.vaulttec.sonarqube.auth.oidc.UserIdentityFactory.create(UserIdentityFactory.java:53)
	at org.vaulttec.sonarqube.auth.oidc.OidcIdentityProvider.callback(OidcIdentityProvider.java:92)
	at org.sonar.server.authentication.OAuth2CallbackFilter.handleOAuth2Provider(OAuth2CallbackFilter.java:94)

The plugins sends an authentication request to the IdP's authentication endpoint with response_type=codeand scope=openid+email+profile. This should start the OIDC authorization code flow with a request of additional claims in the ID token using scope values. But in the token response the IdP (here JetBrain Hub) only returns an ID token with the standard fields (without the requested claims preferred_username, email and name):

{"sub":"e65c9607-fd4e-4bcd-97b1-ca057616590e","aud":"60dcacaf-8a94-4177-b2f2-1348463f88ce","auth_time":1.51579363621E9,"iss":"http:\/\/localhost:8080\/hub","exp":1523569636,"iat":1515793636}

Due to missing UserInfo checks for the requested claims in OidcClient.getUserInfo() SonarQube's UserIdentity.builder() is used with missing arguments.

cpppwner added a commit to cpppwner/sonar-auth-oidc that referenced this issue Jan 12, 2018
This commit fixes the issue vaulttec#3
by quering the user info endpoint when name and preferred username are
both null.

Additional tests are introduced. The data is taken from SonarQube's
web.log which is also attached to the issue.
@tjuerge
Copy link
Contributor

tjuerge commented Jan 12, 2018

Unluckily there are no technical details about the OpenID Connect implementation in JetBrains Hub developer resources. So there's no indication about any support for (via scope) requested claims in the ID token like Keycloak does with it's OIDC Token and SAML Assertion Mappings.

Anyway, if the ID token does not contain the required userprofile and email claims then the plugin must retrieve the UserInfo by an additional network roundtrip to the IdP's user info endpoint.

tjuerge pushed a commit that referenced this issue Jan 13, 2018
* Fix authentication issue with missing profile info

This commit fixes the issue #3
by quering the user info endpoint when name and preferred username are
both null.

Additional tests are introduced. The data is taken from SonarQube's
web.log which is also attached to the issue.

* Cleanup - Remove unused imports

* Fix .travis.yml

The command executed by bash must be passed via the -c option.
@tjuerge tjuerge closed this as completed Jan 16, 2018
@fonsecas72
Copy link

Hi guys, I'm still having this "User login must not be blank" issue. Can you help me?

My userInfo

User info: {"sub":"qwe","ver":"1.0","amr":["pwd"],"iss":"https:\/\/sts.windows.net\/qwe\/","onprem_sid":"qwe","oid":"qwe","uti":"qwe","given_name":"Hugo Fonseca","tid":"qwe","aud":"qwe","unique_name":"qwe@qwe.pt","upn":"qwe@qwe.pt","nbf":1525802951,"name":"Hugo Fonseca BE-UBI","exp":1525806851,"ipaddr":"199.137.170.4","iat":1525802951,"family_name":"BE-UBI"}
java.lang.IllegalArgumentException: User login must not be blank
	at org.sonar.api.internal.google.common.base.Preconditions.checkArgument(Preconditions.java:122)
	at org.sonar.api.server.authentication.UserIdentity$Builder.validateLogin(UserIdentity.java:191)
	at org.sonar.api.server.authentication.UserIdentity$Builder.build(UserIdentity.java:179)
	at org.vaulttec.sonarqube.auth.oidc.UserIdentityFactory.create(UserIdentityFactory.java:53)
	at org.vaulttec.sonarqube.auth.oidc.OidcIdentityProvider.callback(OidcIdentityProvider.java:92)
	at org.sonar.server.authentication.OAuth2CallbackFilter.handleOAuth2Provider(OAuth2CallbackFilter.java:94)
	at org.sonar.server.authentication.OAuth2CallbackFilter.handleProvider(OAuth2CallbackFilter.java:77)
	at org.sonar.server.authentication.OAuth2CallbackFilter.doFilter(OAuth2CallbackFilter.java:70)
	at org.sonar.server.platform.web.MasterServletFilter$GodFilterChain.doFilter(MasterServletFilter.java:126)
	at org.sonar.server.platform.web.MasterServletFilter.doFilter(MasterServletFilter.java:95)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.sonar.server.user.UserSessionFilter.doFilter(UserSessionFilter.java:87)
	at org.sonar.server.user.UserSessionFilter.doFilter(UserSessionFilter.java:71)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.sonar.server.platform.web.SecurityServletFilter.doHttpFilter(SecurityServletFilter.java:72)
	at org.sonar.server.platform.web.SecurityServletFilter.doFilter(SecurityServletFilter.java:48)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.sonar.server.platform.web.RedirectFilter.doFilter(RedirectFilter.java:61)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.sonar.server.platform.web.requestid.RequestIdFilter.doFilter(RequestIdFilter.java:63)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.sonar.server.platform.web.RootFilter.doFilter(RootFilter.java:62)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:108)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
	at ch.qos.logback.access.tomcat.LogbackValve.invoke(LogbackValve.java:256)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)```

@tjuerge
Copy link
Contributor

tjuerge commented May 10, 2018

@fonsecas72 Your IdP doesn't provide the claims preferred_username and email in the user info.

In #10 additional checks for the required claims in the user info are added.

@fonsecas72
Copy link

@tjuerge humm :/ currently I don't have a way to manage idP.

Maybe we could have a way to customize this field? So that I could use "unique_name".

@tjuerge
Copy link
Contributor

tjuerge commented May 11, 2018

@fonsecas72 In your case customizing preferred_username wouldn't help - email is also required (and missing in your user info as well).

So we would end up with customization of every standard user info claim defined in the spec. Sorry, that's not what I'm keen on.

@fonsecas72
Copy link

fonsecas72 commented May 14, 2018

Ok, I might have to fork this plugin then. I believe Jenkins plugin allows this sort of customization though.

Thank you very much @tjuerge

@manish26121981
Copy link

I am integrating Keycloak sso with sonarqube. while login it gives the unauthorized error.
When i see the log file it shows me the following
-No subject alternative names present

2018.09.19 12:24:48 ERROR web[AWXxufUIFR3eNNs8AABj][o.s.s.a.AuthenticationError] Fail to callback authentication with 'oidc'
java.lang.IllegalStateException: Retrieving access token failed
at org.vaulttec.sonarqube.auth.oidc.OidcClient.getTokenResponse(OidcClient.java:162)
at org.vaulttec.sonarqube.auth.oidc.OidcClient.getUserInfo(OidcClient.java:114)
at org.vaulttec.sonarqube.auth.oidc.OidcIdentityProvider.callback(OidcIdentityProvider.java:91)
at org.sonar.server.authentication.OAuth2CallbackFilter.handleOAuth2Provider(OAuth2CallbackFilter.java:94)
at org.sonar.server.authentication.OAuth2CallbackFilter.handleProvider(OAuth2CallbackFilter.java:77)
at org.sonar.server.authentication.OAuth2CallbackFilter.doFilter(OAuth2CallbackFilter.java:70)
at org.sonar.server.platform.web.MasterServletFilter$GodFilterChain.doFilter(MasterServletFilter.java:126)
at org.sonar.server.platform.web.MasterServletFilter.doFilter(MasterServletFilter.java:95)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.sonar.server.user.UserSessionFilter.doFilter(UserSessionFilter.java:87)
at org.sonar.server.user.UserSessionFilter.doFilter(UserSessionFilter.java:71)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.sonar.server.platform.web.SecurityServletFilter.doHttpFilter(SecurityServletFilter.java:72)
at org.sonar.server.platform.web.SecurityServletFilter.doFilter(SecurityServletFilter.java:48)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.sonar.server.platform.web.RedirectFilter.doFilter(RedirectFilter.java:61)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.sonar.server.platform.web.requestid.RequestIdFilter.doFilter(RequestIdFilter.java:63)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.sonar.server.platform.web.RootFilter.doFilter(RootFilter.java:62)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:108)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at ch.qos.logback.access.tomcat.LogbackValve.invoke(LogbackValve.java:256)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1964)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:328)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:322)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1614)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1052)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:987)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1072)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(HttpURLConnection.java:1334)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1309)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:259)
at com.nimbusds.oauth2.sdk.http.HTTPRequest.toHttpURLConnection(HTTPRequest.java:798)
at com.nimbusds.oauth2.sdk.http.HTTPRequest.send(HTTPRequest.java:866)
at org.vaulttec.sonarqube.auth.oidc.OidcClient.getTokenResponse(OidcClient.java:158)
... 45 common frames omitted
Caused by: java.security.cert.CertificateException: No subject alternative names present
at sun.security.util.HostnameChecker.matchIP(HostnameChecker.java:145)
at sun.security.util.HostnameChecker.match(HostnameChecker.java:94)
at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:455)
at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:436)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:200)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1596)
... 60 common frames omitted

@tjuerge
Copy link
Contributor

tjuerge commented Sep 19, 2018

@manish26121981 as stated in the exception (java.security.cert.CertificateException: No subject alternative names present) this is an issue with the SSL certificate of your IdP. Here Java's security subsystem is complaining about missing entries in the certificate's SAN field.
Starting with Java Update 181 the SAN field check is enabled by default.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants