I am trying to create Google SAML SSO custom app integration for my Rails website. I am using omniauth-saml gem.
However, I am really confused with "ACS URL" and "Entity ID" that needs to be set under "Service Provider Details" during google saml idp setup.
I have a few questions:
What should be the ACS URL?
My understanding: It should be the URL at which the SAML assertion should be received sent by Google. If that is correct, what is the use of :assertion_consumer_service_url, which can be set in rails app as:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :saml,
:assertion_consumer_service_url => "acs url here!!" # http://www.my-rails-app.com/sso/saml_asertion_handler
...
end
Will this overwrite the ACS URL set in the google portal and send response to the one specified in the Omniauth config?
What should be the Entity ID?
My understanding: It should be the url of my rails app(http://www.my-rails-app.com). However, I found a few places where saml metadata url is specified(http://my-rails-app.com/auth/saml/metadata).
What should be the issuer in OmniAuth::Builder in rails config?
My understanding: Just like Entity Id, I found it be the 'application name'(http://www.my-rails-app.com) as well as the path to the metadata (http://my-rails-app.com/auth/saml/metadata).
I am very new to this and any guidance is really appreciated.
The google ACS URL is the callback url into your rails app. This is where Google, in your case, sends the SAML response. The default for this is http://example.com/auth/saml/callback.
& 3. The google Entity Id should match exactly the :issuer SAML config property in your rails app. Most people use their domain name for this to reduce the chance of a naming conflict.
ACS is the Assertion Consumer Service URL. It is the destination on the Service Provider (SP) where the SAML Assertion is sent. You have to tell Google as the IDP where to send the assertion. And you have to define the ACS on your SP in Rails. Your entity ID is a unique identifier for your app, usually set to your base domain URL.
Related
I am creating a OAuth2.0 client for a custom OAuth2 provider in Spring Boot + Security (version 5) application.
Below is the application.properties which has all the configuration and there is no additional configuration class in my project.
spring.security.oauth2.client.registration.xxxxxxxxx.client-id=XXXXXXXXXX
spring.security.oauth2.client.registration.xxxxxxxxx.client-secret=XXXXXXXXXX
spring.security.oauth2.client.registration.xxxxxxxxx.scope=openid
spring.security.oauth2.client.registration.xxxxxxxxx.redirect-uri-template=http://localhost:8080/login/oauth2/code/xxxxxxxxx
spring.security.oauth2.client.registration.xxxxxxxxx.client-name=xxxxxxxxx
spring.security.oauth2.client.registration.xxxxxxxxx.provider=xxxxxxxxx
spring.security.oauth2.client.registration.xxxxxxxxx.client-authentication-method=basic
spring.security.oauth2.client.registration.xxxxxxxxx.authorization-grant-type=authorization_code
spring.security.oauth2.client.provider.xxxxxxxxx.authorization-uri=https://api.xxxxxxxxx.com/authorize
spring.security.oauth2.client.provider.xxxxxxxxx.token-uri=https://api.xxxxxxxxx.com/token
spring.security.oauth2.client.provider.xxxxxxxxx.user-info-uri=https://api.xxxxxxxxx.com/userinfo?schema=openid
spring.security.oauth2.client.provider.xxxxxxxxx.user-name-attribute=name
spring.security.oauth2.client.provider.xxxxxxxxx.user-info-authentication-method=header
When i hit http://localhost:8080/ it redirects properly to provider's login page and after successful login it redirects back to my application.
Now the problem is when it redirects then it shows below error message.
I have googled for this error but didn't get any proper answer. Also, the OAuth2 provider didn't share such URL.
After research I came to know that i need to set below property. Should it be provided by Auth Provider?
spring.security.oauth2.client.provider.pepstores.jwk-set-uri
What exactly I am missing here in configuration?
Finally, the problem is solved. I just need to configure the jwk URI which should be provided by the Auth provider.
Below the final configuration for customer Auth Provider.
spring.security.oauth2.client.registration.xxxxxxxxx.client-id=XXXXXXXXXX
spring.security.oauth2.client.registration.xxxxxxxxx.client-secret=XXXXXXXXXX
spring.security.oauth2.client.registration.xxxxxxxxx.scope=openid
spring.security.oauth2.client.registration.xxxxxxxxx.redirect-uri-template=http://localhost:8080/login/oauth2/code/xxxxxxxxx
spring.security.oauth2.client.registration.xxxxxxxxx.client-name=xxxxxxxxx
spring.security.oauth2.client.registration.xxxxxxxxx.provider=xxxxxxxxx
spring.security.oauth2.client.registration.xxxxxxxxx.client-authentication-method=basic
spring.security.oauth2.client.registration.xxxxxxxxx.authorization-grant-type=authorization_code
spring.security.oauth2.client.provider.xxxxxxxxx.authorization-uri=https://api.xxxxxxxxx.com/authorize
spring.security.oauth2.client.provider.xxxxxxxxx.token-uri=https://api.xxxxxxxxx.com/token
spring.security.oauth2.client.provider.xxxxxxxxx.user-info-uri=https://api.xxxxxxxxx.com/userinfo?schema=openid
spring.security.oauth2.client.provider.xxxxxxxxx.user-name-attribute=name
spring.security.oauth2.client.provider.xxxxxxxxx.user-info-authentication-method=header
spring.security.oauth2.client.provider.xxxxxxxxx.jwk-set-uri=https://api.xxxxxxxxx.com/jwks
Thanks
When you receive JWT in client application, you need to verify the signature of JWT. To verify the signature you need public key of Auth provider. As per OAuth specifications, Auth provider can expose the public key through a URI and client can use this URI to get the public key to validate the JWT. This is what is missing in your configuration.
I am getting following error while configuring
social login( Janrain )
for x-cart based e-commerce website ( Facebook and Google+)
The tokenUrl or xdReceiver has not been whitelisted
while the tokenUrl that i have set i.e. [www.culturetruck.com][1] is whitelisted. I guess I didn't understand the concept of tokenUrl. Please suggest me what should I use as token URL to receive tokens in X-cart?
1) According to 'Social Login Flow Walkthrough'
http://developers.janrain.com/overview/social-login/social-login-overview/
Janrain posts an access token to your token URL.
Using the access token and your API key, your application can fetch
data about the user through our Social Login REST API.
User data can be served to your site to customize the end-user
experience.
2) X-Cart 4 'Social Login' module uses URLs like these
https://www.culturetruck.com/xauth_return_rpx.php?xid=8bf6ea9554b4b33e4698d0258575d7da
as Token URL.
In this case you have to add these URLs to the whitelist
www.culturetruck.com
culturetruck.com
*.culturetruck.com
cdn-social.janrain.com
according to
https://janrain.zendesk.com/hc/en-us/community/posts/203661356-The-definitive-token-URL-or-xdReceiver-has-not-been-whitelisted-error-thread
3)To create an integration from scratch follow this guide
http://developers.janrain.com/overview/social-login/social-sign-in-migration-guide/#Step_3Generate_New_Code
This is about Token URL
http://developers.janrain.com/overview/social-login/implementing-social-login/#4_Create_a_Server-side_Token_URL
I'm having trouble configuring my Twitter Oauth in a RubyonRails webapp.
The full trace error: http://pastebin.com/2yf1cE8E
The User.rb http://pastebin.com/UUTiTKvy
The app controller http://pastebin.com/bK9ghUJR
The session controller http://pastebin.com/kxYRd1TU
The routes.rb http://pastebin.com/bt7HMRFy
Omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :twitter, 'JsR9zFGrVuDYuFueRnBQK9tpp', ' tDubF5v9uDRvfio7UBZd2XlFYUQQrftE7Qzk6FPaNOucOTWVlf'
end
Thanks, Alex.
Looking at the error, I think you did not define the callback url of Twitter. You have to go into twitter applications and define the URL of your webapp in your callback.
Looking at the error and the code you provided, you're not properly authenticating to Twitter. The 401 response is basically telling you that Twitter doesn't like the identity information you're passing in. So I would verify your keys are correct, and that OmniAuth doesn't require any additional configurations (e.g. specific endpoints Your second key in the Omniauth middleware code appears to have additional spaces in it, you may have done that for security purposes, but I'm pretty sure that keys shouldn't start with spaces.
IMPORTANT NOTE: Once you've confirmed a fix, you should request new keys for your Twitter account, as they have been posted publicly to this forum.
Questions:
1) What's the best way to integrate OpenID Connect authentication into a webapp that uses Spring Security for authentication?
2) Is there any way - either from the MITREid side of things or the Google Accounts side of things - to get the MITREid OpenID Connect authentication filter to work with Google's OpenID Connect service?
I'm sure answers to these questions will be useful for any developer that uses the Spring Security OpenID module to authenticate with Google.
Detail:
My webapp uses Spring Security's OpenID module (<openid-login .../>) for authentication with Google Accounts as the Identity Provider. ie., users authenticate using their Google Apps or GMail email address.
Recently, whenever users authenticate, they receive this warning message from Google accounts:
Important notice: OpenID2 for Google accounts is going away on April
20, 2015.
So Google is dropping support for OpenID, will turn it off completely in April 2015, and states that you must switch to the OpenID Connect protocol if you want to authenticate with Google Accounts.
I was hoping Spring Security would have built-in support for OpenID Connect, just like it has built-in support for OpenID. e.g. something like an <openid-connect-login .../> element. But my searches have turned up no such support.
The best candidate I've found so far is MITREid Connect . It includes a Spring Security authentication filter named OIDCAuthenticationFilter for OpenID Connect. The problem is, it does not interoperate with Google's OpenID Connect implementation.
I tried cloning the MITREid simple-web-app and configured it to authenticate (using OpenID Connect) with Google Accounts. But it did not work because it depends on a nonce which Google's OpenID Connect implementation does not support. The error message from Google accounts was:
Parameter not allowed for this message type: nonce
Next I tried plugging my own implementation of MITREid's AuthRequestUrlBuilder interface into the MITREid configuration. The only difference between my implementation and MITREid's implementation was that I did not send the nonce.
Not sending the nonce made Google's OpenID Connect implementation happy but MITREid threw an exception when it couldn't find a nonce in the Google authentication response. The error message was:
Authentication Failed: ID token did not contain a nonce claim
I tracked the MITREid exception down to these lines in MITREID'S OIDCAuthenticationFilter:
// compare the nonce to our stored claim
String nonce = idClaims.getStringClaim("nonce");
if (Strings.isNullOrEmpty(nonce)) {
logger.error("ID token did not contain a nonce claim.");
throw new AuthenticationServiceException("ID token did not contain a nonce claim.");
}
But there is no way for me to extend MITREid's implementation to ignore the nonce. So close but yet so far! If Google Accounts would accept the nonce or MITREid could be configured to ignore the nonce then we'd have a solution.
Within the MITREid Connect issues list on github I've found others have run into these similar issues:
1) #726 - Documentation on using client with Google as authentication provider
2) #704 - Add a useNonce attribute into ServerConfiguration to indicate if the IdP accepts the nonce value into its requests.
So I am stuck. Come April 2015 Google will shutdown Open ID authentication.
Some relevant links:
1) https://support.google.com/accounts/answer/6135882
2) https://www.tbray.org/ongoing/When/201x/2014/03/01/OpenID-Connect
3) https://github.com/mitreid-connect
4) https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server/blob/master/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java
5) https://github.com/mitreid-connect/simple-web-app
6) https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server/blob/master/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/PlainAuthRequestUrlBuilder.java
7) https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server/issues/726
8) https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server/pull/704
2015-02-18 Update
Functionality has recently been added to the development branch of mitreid-connect for disabling the nonce - therefore making Google's OIDC server happy. Thankfully, mitreid-connect has also provided some guidance on interoperating with Google .
Unfortunately the "nonceEnabled" change is not yet available in Maven central but hopefully that will change soon.
AFAIK, there is no clean and easy Spring Security migration from OpenID to OpenID Connect authentication. Implementing OpenID authentication with Spring Security is straight-forward using the well documented <openid-login/> but there exists no analog for OpenID Connect.
The MITREid alternative is still on a development branch and unavailable at Maven Central and therefore not a candidate.
In the comments, Chuck Mah points to How to implement Openid connect and Spring Security where Romain F. provides the sample code.
Romain's sample code pointed me in the right direction. Given time is running out, I went with romain's approach, which was to write a custom Spring Security AuthenticationFilter that uses spring-security-oauth2 to query the oauth2 api userinfo endpoint (for Google that's https://www.googleapis.com/oauth2/v2/userinfo). The assumption is that if we are able to successfully query the userinfo endpoint then the user has successfully authenticated so we can trust the information returned - eg the user's email address.
When i first started learning about OpenID Connect the “id token” seemed to be the central concept. However, browsing the spring-security-oauth2 source code, it appears to be ignored. This leads to the question, what’s the point of the ID token if we can authenticate without it (by simply querying oauth2 userinfo endpoint)?
A minimalist solution - which i would prefer - would simply return a validated ID token. There would be no need to query the userinfo endpoint. But no such solution exists in the form of a Spring Security authentication filter.
My webapp was not a spring-boot app like romain's. spring-boot does alot of configuration behind the scenes. Here are some of the problems/solutions I encountered along the way:
problem: HTTP Status 403 - Expected CSRF token not found. Has your session expired?
solution: java config: httpSecurity.csrf().disable()
problem: HTTP Status 500 - Error creating bean with name 'scopedTarget.googleOAuth2RestTemplate': Scope 'session' is not active for the current thread;
solution: java config: OAuth2RestTemplate does not need to be session scoped (OAuth2ClientContext is already session scoped and that's all that's necessary)
problem: HTTP Status 500 - Error creating bean with name 'scopedTarget.oauth2ClientContext': Scope 'session' is not active for the current thread;
solution: web.xml: add RequestContextListener
explanation: because the oauth2ClientContext session-scoped bean is accessed outside the scope of the Spring MVC DispatcherServlet (it is being accessed from OpenIdConnectAuthenticationFilter, which is part of the Spring Security filter chain).
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
problem: org.springframework.security.oauth2.client.resource.UserRedirectRequiredException: A redirect is required to get the users approval.
solution: web.xml: Add filter definition immediately PRECEEDING springSecurityFilterChain
<filter>
<filter-name>oauth2ClientContextFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>oauth2ClientContextFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Unfortunately, OpenID Connect does not allow us to request only email scope.
When our users authenticated using OpenID they would see a consent screen like "webapp would like to view your email address" with which they were comfortable. Now we must request scopes openid email resulting in a consent screen asking the user to share their entire public profile with us ... which we really don't need or want ... and users are less comfortable with this consent screen.
I'm following Brock's tutorial on OAuth2 identity providers: OAuth2 in Thinktecture IdentityServer : OAuth2 identity providers and I'm having problems trying to setup each provider details. I'm trying to use google and facebook.
Google: What I've done is. I've created new project, within which I've gone to APIs & auth > Credentials > Create New Client ID and then chose "Web Application" option. On "Client ID for web application" panel in "Javascript Origins" section I have pasted base URL of my IdSrv (https://somename). I have copied Client ID and Client secret and pasted both into appropriate sections in IdSrv identity provider shown in tutorial. When I run the application I get the invalid_request error from Google saying Invalid parameter value for redirect_uri: Non-public domains not allowed: https://somename/idsrv/issue/hrd/oauth2callback
In case of Facebook, I've created new App, and was trying to set "Site URL" in basic settings to https://somename, but got an alert saying "must be a URL with a valid domain." which I believe is essentially the same as what the Google error message is saying
My question is: How can I deploy a test version of my IdSrv then? I just want a quick and simple environment for testing purposes for now. Am running the IdSrv in my local IIS, was following Dominick installation tutorial video Thinktecture IdentityServer v2 Tutorial: Installation
When we setup IdentityServer for local testing we configure it to run under IIS with a custom host name and then setup a entry in the local hosts file. To google this should appear as a public URL.
An easier approach is to use one of the localhost DNS services that exist.
For example, whatever.vcap.me resolves to 127.0.0.1 as does production.vcap.me, staging.vcap.me and development.vcap.me.