Google is deprecating the OpenID endpoint I was using (v1.0 I think, via the django_openid_auth
module) and I need to update my app and migrate my users' accounts to use Google OAuth2.
I've changed the app to use python-social-auth
and have it authenticating with social.backends.google.GoogleOAuth2
successfully.
I've written a pipeline function to find associated OpenID urls from the old table and this is working for the other backends I care about but Google:
def associate_legacy_user(backend, response, uid=None, user=None,
*args, **kwargs):
if uid and not user:
# Try to associate accounts registered in the old openid table
identity_url = None
if backend.name == 'google-oauth2':
# TODO: this isn't working
identity_url = response.get('open_id')
else:
# for all other backends, see if there is a claimed_id url
# matching the identity_url use identity_url instead of uid
# as uid may be the user's email or username
try:
identity_url = response.identity_url
except AttributeError:
identity_url = uid
if identity_url:
# raw sql as this is no longer an installed app
user_ids = sql_query.dbquery('SELECT user_id '
'FROM django_openid_auth_useropenid '
'WHERE claimed_id = %s',
(identity_url,))
if len(user_ids) == 1:
return {'user': User.objects.get(id=user_ids[0]['user_id'])}
As best I can tell from reading Google's migration guide, I need to add an openid.realm
to the request, which I've done as follows in settings.py:
SOCIAL_AUTH_GOOGLE_OAUTH2_AUTH_EXTRA_ARGUMENTS \
= {'openid.realm': 'http://example.com/'}
But this doesn't seem to be returning the open_id
value in the response
passed into my pipeline function.
I seem to be stuck on Step 3:
I tried sub-classing the backend to change the RESPONSE_TYPE to add
id_token
but that returned an empty response:import social.backends.google class CustomGoogleOAuth2(social.backends.google.GoogleOAuth2): RESPONSE_TYPE = 'code id_token'
I tried building an additional request to
https://www.googleapis.com/oauth2/v3/token
similar to this example, but I don't really know how to go about putting that together and debugging it.
Some more details:
- My old
claimed_id
s for Google OpenID users look like: https://www.google.com/accounts/o8/id?id=AItOawmAW18QuHDdn6PZzaiI5BWUb84mZzNB9eo - I'm happy to use
social.backends.google.GoogleOpenIdConnect
or a similar alternative backend if that's an easier solution. And while it seems to be closer to what the Google docs are talking about, I wasn't able to get it to work when I tried:- I get a 400 Error: invalid_request Parameter not allowed for this message type: nonce
- I can get past the
nonce
error usingsocial.backends.google.GoogleOpenIdConnect
by addingid_token
to theRESPONSE_TYPE
but then I get anAuthMissingParameter
error in my/complete/google-openidconnect/
endpoint as the request's GET and POST are empty. (Tried 'code id_token', 'token id_token', 'id_token', ...)
- I don't want to use
social.backends.google.GooglePlusAuth
as that doesn't integrate as nicely with my current login form. - Worst case, I should be able to use
social.pipeline.social_auth.associate_by_email
, but I only have email addresses for maybe 80% of the users so that leaves quite a few who will have a new account and need support to associate it manually.
Try as I might, I can't find any examples of people doing a similar migration with python-social-auth
, but it must be happening to lots of people.
Any ideas?