Closed stanhu closed 11 years ago
Quoting from above: "This works for those rare OpenID providers (currently, only Google GMail) who generate domain-specific identifiers."
I am really wondering, given that is a Google specific problem, why don't you use Google OAuth2 instead?
I did get Google OAuth2 working, but I ran into a number of issues:
1) Google OAuth2 requires you to register a fixed callback URL. This is really inconvenient if lots of developers need to run a local server. I could have a development test secret and callback, but if someone wants to run on a different port he has to register a new API client. Google OpenID is a lot easier in this respect, since the callback URL is specified as a parameter.
2) I switched the scope of the Google provider from the suggested 'https://www.googleapis.com/auth/userinfo.profile' to 'https://www.googleapis.com/auth/userinfo.email' so that I could use the AUTO_SIGNUP option. The GoogleOauth2Adapter assumes the return string has the field 'id' (line 37), so this fails. That code needs to be modified to handle the case where 'email' and 'verified_email' are the only values returned to 'extra_data'.
3) I had some trouble initially getting Google OAuth2 working out of the box. I kept getting an ugly error (SocialApp does not exist) until I realized that you have to go into the admin page and manually add the API information into the database. I see that it is mentioned in the 'Architecture & Design' section of README, but I think it would help if this reminder were put into somewhere closer to the provider details.
Thanks for the great work on this module!
My point 2 isn't quite right. Apparently if you have a SCOPE definition in SOCIALACCOUNT_PROVIDERS, the logic in GoogleProvider.get_default_scope() to add the USERINFO_EMAIL scope isn't actually run. That's because OAuth2Provider.get_scope() gets called, retrieves the SCOPE definition, and never executes GoogleProvider.get_default_scope() if there is one already defined.
You either have to leave out the SCOPE definition or add in both values to make QUERY_EMAIL work, such as:
SOCIALACCOUNT_PROVIDERS = \
{ 'google':
{ 'SCOPE': ['https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/userinfo.email'] } }
Things now behave as I would hope, except point 1 about the fixed callback is a big drawback to our system.
At the Google API console you can list multiple callback URLs. Options:
I do understand that from a development point of view OpenID may be easier. How about the end user experience though? The OAuth2 flow is much better looking, even allowing you to put in your own logo et al.
Don't get me wrong, I am not really against the stackoverflow approach, though I am really wondering why one would go through all the trouble. Sure, it may ease development, but IMHO user experience suffers from that.
Thanks. In principle, I agree with everything you have to say about OAuth2. I switched our application to OAuth2 and loaded the client API/secret automatically with a Django fixture.
The biggest downside I see now is that OAuth2 doesn't allow you to:
-Use unqualified hostnames (e.g. http://test-server:8000) -Use raw IP addresses (e.g. http://192.168.1.10:8000)
This makes it an additional pain for developers. I may continue on the OpenID "trusted providers" track just for that reason.
It does allow http://localhost:8000/accounts/google/login/callback/ which should be sufficient for development purposes?
Yeah, I used the localhost trick, but we have developers who want to access their local machines via direct IP address to see how things will look on an tablet or a phone. The fallback is to login directly with the e-mail account or username, but it would be nice not to have to do that.
Developer experience is indeed suboptimal, but is (IMHO) worth it given that end users benefit from a nicer UX. For now I am closing this issue...
I would like the ability to trust certain providers (e.g. Google OpenID) to supply a verified e-mail address so that I can access the system from different URLs without having to create a new account. Another words, I'm trying to solve the problem where if you login successfully with, say, http://localhost:8000 one day, and then decide to run the same server as http://localhost:9000 another day, that the different Uids generated from these URLs will still point to the same account.
StackOverflow has the best overview about the problem and what they did:
http://blog.stackoverflow.com/2010/04/openid-one-year-later/
"That’s a major bummer for site networks like us with multiple domains. We use the OpenID string as your user “fingerprint”, so if your “fingerprint” changes, we can’t tell who you are any more. It’s a frustrating problem, but we think we’ve finally come up with a fix: we demand email from Google GMail OpenIDs!
If we have an email address from a verified OpenID email provider (that is, an OpenID from a large email service we trust, like Google or Yahoo), then it’s guaranteed to be a globally unique string. We treat this as part of the identifying user token, attached only at login time, that is not editable by the user.
So our cross-site user account matching now works this way:
Match by GUID. This is something we generate and assign during account association, so it’s a perfect fingerprint. Match by OpenID URL. This works for the vast majority of OpenID providers. Match by OpenID provided email address … if you are on our trust whitelist. This works for those rare OpenID providers (currently, only Google GMail) who generate domain-specific identifiers. This satisfies all known OpenID providers, so we can now potentially associate your accounts, across all of our websites, automatically. You’ll still have to log in, of course, but the login itself could trigger account association for every site in the network.
There is one, and only one downside: we must demand email from Google OpenIDs. Email is not usually required to use our sites, but you can’t log in via Google if you refuse to provide email to us. You can always switch OpenID providers, of course, but we regretfully must make the email demand mandatory in the case of Google."
I took a pass at hacking django-allauth to do something like this, but I don't think it's quite secure:
https://github.com/stanhu/django-allauth/commits/master
Do you have any opinions on:
1) Is this a good idea to provide a similar feature? 2) If so, what is the best approach? 3) How to improve upon what I attempted?