Python-social-auth using Django server hostname an

2020-07-22 03:38发布

问题:

I'm using python-social-auth with Django to authenticate with Google using Oauth2 (google-oauth2). In my template I use something like:

<a href="{% url "begin:social" "google-oauth2" %}">Login</a>

And it correctly creates an A element pointing to the correct login url. The thing is, django is running with runserver option behind Apache with ProxyPass and ProxyPassReverse (also tried nginx with proxy_pass option, not fcgi).

In this scenario I have two problems; first, when creating the authentication request, python-social-auth sends the parameter redirect_uri as localhost:8000 so I did this on settings.py:

AUTH_EXTRA_ARGUMENTS = {'redirect_uri': 'http://myapp.com'}

And it bypasses the "Bad Request" Google response that is returned if I send localhost:8000 as redirect_uri.

Then, in python-social-auth oauth.py, here, I can see that

self.auth_complete_params(self.validate_state())

Is sending the same wrong redirect_uri to Google. So I did something ugly like:

data = self.auth_complete_params(self.validate_state())
data['redirect_uri'] = 'http://myapp.com'
response = self.request_access_token(
    self.ACCESS_TOKEN_URL,
    data=data, # ugh!
    headers=self.auth_headers(),
    method=self.ACCESS_TOKEN_METHOD
) 

So, that's my current solution. I just don't understand on how to do this on a more elegant way, or the "correct" way.

Any help out there?

Best

回答1:

If I got that right, the problem is that python-social-auth is creating the wrong redirect_uri to send to the auth provider. It always sends http://localhost:8000/my-login-page but you want it to send http://myapp.com/my-login-page .

The right place to specify the redirect URI is in settings.py:

SOCIAL_AUTH_LOGIN_REDIRECT_URL = 'http://myapp.com/my-login-url'

and similar settings for special cases (e.g. SOCIAL_AUTH_NEW_USER_REDIRECT_URL). Then, you need to tell python-social-auth to let you change the domain, otherwise it will force the domain back to localhost:8000. Do this:

SOCIAL_AUTH_SANITIZE_REDIRECTS = False

(It is also possible to fix this across all of Django by giving hints to its build_absolute_uri() method about what domain to use. This involves more pieces of your stack but check it out in this answer).



回答2:

I have Django 1.9 and python-socail-auth 0.2.13

settings.py:

INSTALLED_APPS = [
  ...
  'social.apps.django_app.default',
]

SOCIAL_AUTH_RAISE_EXCEPTIONS = True
RAISE_EXCEPTIONS = True

AUTHENTICATION_BACKENDS = (
  'social.backends.google.GoogleOAuth2',
  'django.contrib.auth.backends.ModelBackend',
)

SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = '***'
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = '***'

SOCIAL_AUTH_PIPELINE = (
'social.pipeline.social_auth.social_details',
'social.pipeline.social_auth.social_uid',
'social.pipeline.social_auth.auth_allowed',
'social.pipeline.social_auth.social_user',
'social.pipeline.user.get_username',
'social.pipeline.social_auth.associate_by_email',  
'social.pipeline.user.create_user',
'social.pipeline.social_auth.associate_user',
'social.pipeline.social_auth.load_extra_data',
'social.pipeline.user.user_details',
)

urls.py:

urlpatterns = [
  ...
  url(r'', include('social.apps.django_app.urls', namespace='social')),
  url(r'', include('django.contrib.auth.urls', namespace='auth')),
]

In template:

 <a href="{% url 'social:begin' 'google-oauth2' %}?next={% url 'dashboard' %}">Google</a> |

Google Developers Console -> App -> Credentials -> OAuth 2.0 client IDs-> Client ID for Web application:

Authorized JavaScript origins: 
  http://127.0.0.1:8000

Authorized redirect URIs: 
  http://127.0.0.1:8000
  http://127.0.0.1:8000/complete/google-oauth2/