SAML-Toolkits / php-saml

Simple SAML toolkit for PHP
MIT License
1.23k stars 473 forks source link

Having multiple Google accounts (using the hd parameter) #598

Open Biganon opened 1 month ago

Biganon commented 1 month ago

I'm using Google as an SAML IdP for my app.

It works, but when a user has 2 Google accounts (say, one for work and one for leisure), during the login process they see the account chooser. This doesn't really make sense, because we know we want to choose the address that ends with @mycompany.com .

Worse : if they pick the wrong account (the one that isn't configured to work with my app), they get an error, and still get a cookie according to which this account should be used, and they can't reach the account chooser anymore...

According to this link, Google accepts an hd parameter with the domain name you want to automatically pick, and it works great.

Only problem is, it only works on the account chooser page. That's not the page on which we land when connecting with SAML (https://accounts.google.com/o/saml2/something). When adding the hd parameter to this URL (which php-saml lets us do easily with the parameters argument of the login method), it is encoded with the rest of the URL, and passed to the account chooser, as a GET parameter called continue. Therefore the account chooser doesn't receive the actual hd parameter... in other words, the account chooser's url is like https://accounts.google.com/AccountChooser/signinchooser?continue=https%3A%2F%2Faccounts.google.com%2Fo%2Fsaml2%2Fcontinue%3Fidpid%3Dblah_blah_encoded_url%2Fhd%3Dmy_hd_parameter

Any idea what we could do?

Thanks in advance

PS : if I'm not being clear enough, please just see the link I've included, and consider that I would like to achieve exactly what it is that they're doing, but while using php-saml)

Biganon commented 1 month ago

Cf. https://github.com/SAML-Toolkits/php-saml/issues/213 , same issue.

It is indeed a problem on Google's side, but I feel like a simple solution with php-saml either already exists (and I haven't found it yet), or would be feasible.

pitbulk commented 1 month ago

If you are sending a SAMLRequest via HTTP-Redirect

https://accounts.google.com/o/saml2?idpid=xx&hd=yy

and you end at

https://accounts.google.com/AccountChooser/signinchooser?continue=

It is clear that Google has not recognized the hd parameter.

I tried to search an official Google doc describing hd, but only found references to the OIDC protocol.

If you are trying to execute an SP-initiated flow, what happens if rather than using an AuthNRequest authentication, you instead redirect the user to:

https://accounts.google.com/AccountChooser/signinchooser?hd=yy&continue=(<SP_initiated_SSO_URL>)

Example:

https://accounts.google.com/AccountChooser/signinchooser?hd=domain.com&continue=https%3A%2F%2Fsp.example%2Fsaml%2Flogin

Maybe if the user selected the account, is not asked again to select the account.

Alternative: Have you tried to send the email in the NameID

So basically at your app you request user for its email, and then build the AuthNRequest to include that parameter. I have no tested but maybe that bypasses the need of AccountChooser.

See nameIdValueReq

Biganon commented 1 month ago

If you are trying to execute an SP-initiated flow, what happens if rather than using an AuthNRequest authentication, you instead redirect the user to [...]

Yup that's what I'm trying to achieve now, but I feel like it implies modifying the lib itself, to "manually" build the AccountChooser URL with whatever weird combination of triply-urlencoded parameters Google is using at this step

Biganon commented 3 weeks ago

Here's a dirty hack I've made that solves the problem, allowing you to append &hd=example.com at the end of the SSO URL. If someone feels like cleaning it up and making a PR, feel free. google_hd_parameter.patch.txt