使用Django allauth谷歌登录成功但无法获取Access Token的问题
Django allauth谷歌登录获取Access Token问题解决
我正在使用Django allauth实现谷歌身份认证功能,目前已成功完成谷歌登录,但无法获取Access Token,数据库中也未存储该Token。请问如何从谷歌登录中获取Access Token?
现有配置文件展示
settings.py
from pathlib import Path import os # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent # Quick-start development settings - unsuitable for production # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'django-insecure-9#c!e&s(-o9-6u^mt#w(w6s$ober^f(m45)=f)=m&zo1$dlcg&' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'allauth', # Social login App 'allauth.account', # login App 'allauth.socialaccount', # Social login App 'allauth.socialaccount.providers.google', # Google login App 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', "API", # API APP ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', "allauth.account.middleware.AccountMiddleware" ] ROOT_URLCONF = 'MassMail.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [ os.path.normpath(os.path.join(BASE_DIR, 'templates')), ], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', 'django.template.context_processors.request', # requirements for django-all-auth ], }, }, ] WSGI_APPLICATION = 'MassMail.wsgi.application' # Database DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', } } # Password validation AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Google Authentication SITE_ID = 1 AUTHENTICATION_BACKENDS = [ 'django.contrib.auth.backends.ModelBackend', 'allauth.account.auth_backends.AuthenticationBackend', ] LOGIN_REDIRECT_URL = '/accounts/profile/' # Provider specific settings SOCIALACCOUNT_PROVIDERS = { 'google': { 'FETCH_USERINFO' : True, 'SCOPE': [ 'profile', 'email', 'https://www.googleapis.com/auth/gmail.modify', 'https://www.googleapis.com/auth/gmail.send', ], 'AUTH_PARAMS': { 'access_type': 'online', }, 'OAUTH_PKCE_ENABLED': True, } } # Internationalization LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_TZ = True # Static files (CSS, JavaScript, Images) STATIC_URL = 'static/' # Default primary key field type DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
项目urls.py
from django.contrib import admin from django.urls import path,include urlpatterns = [ path('admin/', admin.site.urls), path("accounts/", include("API.urls")), ]
API urls.py
from django.urls import path,include from . import views urlpatterns = [ path("profile/",views.ProfileView.as_view(),name='user_profile'), path('', include("allauth.urls")), ]
解决步骤
1. 修改谷歌Provider的授权类型
在settings.py的SOCIALACCOUNT_PROVIDERS配置中,将谷歌的access_type从online改为offline:
'SOCIALACCOUNT_PROVIDERS': { 'google': { # ... 其他配置 'AUTH_PARAMS': { 'access_type': 'offline', # 修改这里 }, # ... 其他配置 } }
online模式仅返回短期有效且不持久化存储的Access Token,而offline模式会请求离线访问权限,不仅会返回Access Token,还会生成Refresh Token,并且allauth会自动将这两个Token存储到数据库中。
2. 确保Token存储功能开启
在settings.py中显式添加以下配置,确认allauth开启Token存储:
SOCIALACCOUNT_STORE_TOKENS = True
这是allauth的默认配置,但显式声明可以避免因环境差异导致的问题。
3. 重新授权登录
修改配置后,需要让用户退出当前登录并重新通过谷歌授权登录——因为之前的授权请求没有包含offline权限,旧的授权记录不会生成可存储的Token。
4. 在视图中获取Access Token
登录完成后,你可以在视图中通过用户关联的SocialAccount和SocialToken模型获取Token。以你的ProfileView为例:
from django.views import View from django.http import HttpResponse from allauth.socialaccount.models import SocialAccount, SocialToken from allauth.socialaccount.providers.google.provider import GoogleProvider class ProfileView(View): def get(self, request): if not request.user.is_authenticated: return HttpResponse("请先登录") # 获取用户关联的谷歌社交账户 google_account = SocialAccount.objects.filter( user=request.user, provider=GoogleProvider.id ).first() if not google_account: return HttpResponse("未关联谷歌账户") # 获取对应的Token记录 social_token = SocialToken.objects.filter(account=google_account).first() if social_token: access_token = social_token.token refresh_token = social_token.token_secret # 这里可以将Token用于后续业务逻辑,比如调用Gmail API return HttpResponse(f"Access Token: {access_token}<br>Refresh Token: {refresh_token}") return HttpResponse("未获取到Token,请重新授权登录")
5. 验证数据库存储
重新登录后,你可以检查数据库中的socialaccount_socialtoken表,里面应该会生成一条关联该用户谷歌账户的记录,包含token(Access Token)和token_secret(Refresh Token)字段。
内容的提问来源于stack exchange,提问作者Akrash Nadeem
相关产品推荐
相关产品推荐

