How or when to follow redirected OpenIDs?
Asked Answered
E

2

11

I'm currently implementing OpenID authentication for a website. During testing, I've noticed that Google accepts different versions of claimed Google Profile IDs, e.g.:

Interestingly, the verified ID differs as well (for the samples above, same order):

Of course, this makes looking up the associated user account quite difficult, not to say impossible. Interestingly, all above IDs work for Stackoverflow. So I thought that there has to be some normalization step I'm missing in my implementation - or SO does some specialized voodoo to get things straight.

Looking at 7.2 Normatlization of the OpenID Authentication spec I found this:

URL Identifiers MUST then be further normalized by both following redirects when retrieving their content and finally applying the rules in Section 6 of [RFC3986] to the final destination URL. This final URL MUST be noted by the Relying Party as the Claimed Identifier and be used when requesting authentication.

Following redirects of claimed IDs doesn't help too much as I'm still left with two different IDs:

Looking at redirects of verified IDs is much more helpful though as I always end up with this one:

Okay, looks like I should follow redirects of verified IDs, not claimed IDs.

The question now: Is it secure to follow redirects of claimed/verifed IDs, e.g. before search the DB like so:

do {
  user = lookup(verifiedId)
  if (user is null)
    response = fetchUrl(verifiedId)
    if (response.location is null) {
      break # no redirect, jump out of loop, unknown user
    } else {
      verifiedId = response.location # use redirect location
    }
} while (user is null)

return user;

If yes, I suspect that this should not only be done when looking up a user but when storing a new ID as well, right?

(If I should really follow redirect, I have another question about potential malicious redirects, but that will have to wait until I get an answer to this one. Might become obsolete anyway)

Epp answered 10/6, 2011 at 16:49 Comment(2)
"stefan.fussenegger" and "stefanfussenegger" are same in Google's world. It normalizes the dot to avoid confusing usernames that are 99% similar.Hohenlohe
@Hohenlohe yeah, that's clear. I'd like to avoid a Google specific solution though. At least if there is a globally valid approach.Epp
C
1

Open ID 2.0 says that during discovery,

URL Identifiers MUST then be further normalized by both following redirects when retrieving their content and finally applying the rules in Section 6 of [RFC3986] to the final destination URL. This final URL MUST be noted by the Relying Party as the Claimed Identifier and be used when requesting authentication.

So, according to this, you should take the user-supplied identifier and normalize it by following redirects & following normal URL normalization procedures.

The result is considered the 'claimed identifier' (CI). Next, you'll do the association dance and determine if this claim is true.

Note - Some providers have a 'well-known' OpenId Provider (OP) URL, for example Google. If you notice the sign-in process for StackOverflow, you can simply click the Google button instead of filling out a form. In this variant, the 'well-known' OP URL is not the users CI. The user did not provide you with a CI. You'll need to wait until you complete the authentication dance and Google tells you who the user is.

It's at this point (after receiving a successful association call-back from the OpenId Provider) that you'll have an identifier for the user. Per section 9.1 you SHALL receive either both an openid.claimed_id and openid.identity, or neither field if you're doing something fancy with extensions (I'm not very familiar with this aspect of the spec).

Now you should store the openid.claimed_id on your end - this will be the identifier unique to this user. This could be different from what the user originally supplied you. It might also be different from where you ended up (after following redirects on the user-supplied identifier). The OpenID Provider has the final say.

In regards to the security of following redirects on the user-supplied identifier. There shouldn't be an issue here. Redirects allow a user to delegate authentication to a provider of their choosing. No matter where the redirects lead you, you will end up asking that OpenId Provider to establish an association with you. When you make this request you'll supply the (normalized) claimed identifier and the provider can decide if they wish to be responsible for the claimed identifier, and they will (somehow in their infinite wisdom) authorize that the user has ownership of this claimed identifier.

Going back to Google, the claimed identifier Google will end up supplying you will look nothing like your examples above. The example they use is openid.claimed_id=https://www.google.com/accounts/o8/id/id=AItOawl27F2M92ry4jTdjiVx06tuFNA (source).

Hope that helps...

Cristincristina answered 20/6, 2011 at 5:27 Comment(3)
I know that Google has a 'well-known' OP URL, I was talking about Google Profile URLs (edited it to be more precise, sorry) which work as well. The four examples are actual results I got from Google: 4 different claimed identifiers, 3 different verified identifiers. following redirects of claimed/verified identifier URLs reduces the number to 2 or 1. So it does work, it just doesn't feel right and I wonder if only Google should do a better job returning only unique verified ID per user. But then again, Stackoverflow doesn't have a problem, so there must be a way to do this.Epp
I admit, it is confusing. But you need to separate the concept of what the user says their identity is and what the provider says the users identify is -- You say your identity is profiles.google.com/stefan.fussenegger/about -- You perform discovery on this location. Look at the response headers (X-XRDS-Location). Points to a XML doc with the URL google.com/accounts/o8/ud?source=profiles. You send the user here. Google sends them back with their 'Official' Claimed Identifier. All your links should lead to the same outcome, one master CI, reported by Google as authoritative.Cristincristina
nothing confusing here. but still, my problem is that Google won't send one unique identifier but 3 different ones. following redirects gets them down to one ... somehow. I'm still not sure how or when to do that.Epp
T
0

I'm using email as uniq identifier at this case. You can request it from google, see http://code.google.com/intl/en/apis/accounts/docs/OpenID.html#Parameters

Twelvemo answered 20/6, 2011 at 4:7 Comment(1)
how do you do authentication using mail addresses? I know it's possible to get them. But I'd be concerned that an OP could send a mail address the user doesn't control, hence giving access to all accounts using mail address only.Epp

© 2022 - 2024 — McMap. All rights reserved.