I'm using Gsuite as an Saml IDP to authentify users of my organisation on internal apps.
Everything is working fine, except for one point: when one of my users if logged in with his/her personal account only, Google will fail with:
403 Error: app_not_configured_for_user
This makes sense as the app is intended to be used by internal users only, but I would like to be able to force Google saml authentication to display the account selector even if the user is already logged in to one account as this is possible for oauth2 with prompt=select_account.
Any way to have the same behavior with SAML ?
[EDIT] I actually managed to achieve what I want by using
https://accounts.google.com/AccountChooser/?continue=$SAML_REQUEST$
[EDIT 2] Here is the code snippet for the adaptation in ruby on rails (using ruby-saml)
config/initializers/saml_override.rb
module OneLogin
module RubySaml
class Authrequest < SamlMessage
GOOGLE_ACCOUNT_CHOOSER_URL = "https://accounts.google.com/AccountChooser?continue="
alias_method :old_create, :create
def create(settings, params = {})
self.old_create(settings, params)
@login_url = GOOGLE_ACCOUNT_CHOOSER_URL + CGI.escape(@login_url)
end
end
end
end
Good that you've resolved your problem. I thought I'd add a few archirectural points.
SAML
ForceAuthn
is a SAML Attribute that you can send in an authentication request. There are others such as EntityId
for apps that need to control which login method should be used.
OPENID CONNECT
This has better options I would say, as a more up to date standard. The JOSE based technologies work well for web and mobile clients, in pretty much any tech stack.
There are a greater number of request parameters such as acr_values
to replace EntityId, and prompt
has more options than ForceAuthn, as you pointed out. This also provides additional session management options as in this recent answer of mine.
PROVIDERS
Not all providers are standards based, and sone may not support ForceAuthn, prompt, acr_values etc, but you may still want to use them for login purposes. To solve your problem you had to resort to a non SAML Google specific request parameter. The more login providers you use, the worse this gets - and application complexity grows.
OPTIMAL ARCHITECTURE
For future reference, it is worth aiming for this architecture, in case any of this is new to you:
Application code only uses OpenID Connect, which is a much larger space than many people are aware of - have a look at this summary of standards.
Apps only redirect to an Authorization Server, which in turn manages connections to identity providers and their peculiarities. These connections can use SAML, OIDC or anything else needed.
The end result should be simple and portable code in apps, which also have support for the most cutting edge authentication flows.
At least that's sonething I like to aim for - identity remains a challenge, sometimes with too many annoyances :).
class SamlController < ApplicationController
def init
request = OneLogin::RubySaml::Authrequest.new
redirect = request.create(saml_settings)
# google doesn't support ForceAuthn so we have to redirect requests to the account chooser first
google_account_url_chooser = "https://accounts.google.com/AccountChooser?continue="
if redirect.include?("https://accounts.google.com")
encoded_redirect = CGI.escape(redirect)
redirect = "#{google_account_url_chooser}#{encoded_redirect}"
end
redirect_to(redirect)
end
def saml_settings
...
end
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With