Question

I'm probably missing something really silly, and missed it in the Google Federated Login documentation, but how is the Google OpenID login actually secure for the requesting site? How does the requesting site know the details are coming from Google and not just someone typing in query string parameters into the URL?

To illustrate, I'm implementing a basic OpenID login sequence in PHP, and all that seems to be returned is a bunch of query string parameters in the URL that I can use to get the OpenID details, which works great. The problem is, if I just typed those into the address bar manually without actually logging in with Google, how would my requesting site know the difference?

First, the form requesting the details:

<form method='post' action='https://www.google.com/accounts/o8/ud'>

    <input type='hidden' name='openid.return_to' value='http://www.example/com/logged-in' />

    <input type='hidden' name='openid.mode' value='checkid_setup' />
    <input type='hidden' name='openid.ns' value='http://specs.openid.net/auth/2.0' />
    <input type='hidden' name='openid.claimed_id' value='http://specs.openid.net/auth/2.0/identifier_select' />
    <input type='hidden' name='openid.identity' value='http://specs.openid.net/auth/2.0/identifier_select' />

    <input type='hidden' name='openid.ns.ax' value='http://openid.net/srv/ax/1.0' />
    <input type='hidden' name='openid.ax.mode' value='fetch_request' />
    <input type='hidden' name='openid.ax.required' value='email,firstname,lastname' />
    <input type='hidden' name='openid.ax.type.email' value='http://axschema.org/contact/email' />
    <input type='hidden' name='openid.ax.type.firstname' value='http://axschema.org/namePerson/first' />
    <input type='hidden' name='openid.ax.type.lastname' value='http://axschema.org/namePerson/last' />

    <input type='submit' value='Login With Google Account' />

</form>

...which works great, sending me back to the requesting site at http://www.example.com/logged-in with a whole bunch of URL parameters, illustrated below (from a PHP print_r call):

Array
(
    [openid_ns] => http://specs.openid.net/auth/2.0
    [openid_mode] => id_res
    [openid_return_to] => http://www.example.com/logged-in
    [openid_ext1_type_firstname] => http://axschema.org/namePerson/first
    [openid_ext1_value_firstname] => {user's first name}
    [openid_ext1_type_email] => http://axschema.org/contact/email
    [openid_ext1_value_email] => {user's e-mail address}
    [openid_ext1_type_lastname] => http://axschema.org/namePerson/last
    [openid_ext1_value_lastname] => {user's last name}
)

...which is awesome, but how do I know that this is in fact a legitimate request, and not someone typing in the above parameters into the address bar?

Thanks for any help, apologies if this has been asked already (couldn't find any replicas!) and if I'm missing something obvious!

Was it helpful?

Solution

Without going into too many details (read the OpenID spec if you need the gory details) the OpenID protocol has safeguards in place for this. The assertions you receive back are signed and verifiable, and there are limitations in how IDs are namespaced to prevent providers from spoofing each other's IDs. If you're using an established library (e.g. php-openid is fine) you shouldn't have to worry too much about this as it's usually taken care of underneath the covers. If you're trying to roll your own implementation....well, just don't...

That said, there are some things that aren't covered in the protocol. For example, while attributes are signed in the response, you can't assume they're accurate unless you trust the particular provider. Some apps will check the URL/hostname of the provider that made the assertion (after verifying the response) and whitelist known identity providers that do proper email verification. If you need a verified email, doing this makes for a better UX. But if the assertion is from an unknown identity provider don't assume the email address actually belongs to the user unless you verify possession yourself.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top