【问题标题】:Google OAuth does not return refresh_token in authlib.starlette_clientGoogle OAuth 不会在 authlib.starlette_client 中返回 refresh_token
【发布时间】:2020-06-18 20:56:18
【问题描述】:

您好,我正在使用 authlib/FastAPI/Google 开发一个用于登录过程的网络应用程序,并希望保留 refresh_token 以便我可以让用户在应用程序中保持足够的时间。

我遵循https://docs.authlib.org/en/latest/client/starlette.html中的标准程序

oauth = OAuth()
oauth.register(
  name='google',
  client_id='xxx',
  client_secret='yyy',
  api_base_url='https://www.googleapis.com/oauth2/v3/',
  access_token_url='https://accounts.google.com/o/oauth2/token',
  authorize_url='https://accounts.google.com/o/oauth2/auth',
  jwks_uri='https://www.googleapis.com/oauth2/v3/certs',
  client_kwargs={
    'scope': 'email openid',
    'access_type': 'offline',
    'prompt': 'consent',
  }
)

from starlette.requests import Request

@app.get("/login")
def login_via_google(request: Request):
    redirect_uri = 'https://example.com/auth'
    return await oauth.google.authorize_redirect(request, redirect_uri)

@app.get("/auth")
def auth_via_google(request: Request):
    token = await oauth.google.authorize_access_token(request)
    user = await oauth.google.parse_id_token(request, token)
    return dict(user)

但是,即使我指定了access_type='offline',令牌也不包含refresh_token。如果我的应用程序已经在我的帐户中注册,我也添加了 prompt='content' 的参数。

我错过了什么吗?

此外,保持refresh_token 是长时间运行用户应用程序的最佳方式吗?我不喜欢打扰用户多次登录。

提前致谢!

【问题讨论】:

    标签: python google-api google-oauth authlib starlette


    【解决方案1】:

    大多数脚本语言仅在用户第一次通过身份验证时返回 refresh_token。假设您已将其保存在系统中并正在使用它,因此不需要另一个。因此,所有其他对用户进行身份验证的尝试都不会包括它。

    您可以尝试强制他们使用re-consent,但我不确定这是否会强制使用新的刷新令牌。看起来你正在这样做,所以它不起作用。

    在这种情况下,您可能需要撤消用户访问权限并再次请求。除非你有令牌然后Token revoke 然后让他们再次登录,你应该会看到一个刷新令牌

    如果所有其他方法都失败,请用户进入他们的谷歌帐户并删除您的应用程序对其帐户的访问权限,然后尝试登录。这就像完全重新开始一样,并且会给你一个刷新令牌。

    【讨论】:

    • 感谢您的建议!但实际上我已经完成了所有这些操作,正如您所见,'prompt': 'consent' 已经在代码 sn-p 中。我从我的帐户管理中删除了该应用,但仍然是同样的问题。
    【解决方案2】:

    我也遇到了这个问题。 client_kwargs 中似乎只允许使用一些参数:

    EXTRA_AUTHORIZE_PARAMS = (
        'response_mode', 'nonce', 'prompt', 'login_hint'
    )
    

    也许作者试图禁止特定于实现的参数?一种解决方法似乎是将access_type=offline 添加到authorize_url

    authorize_url='https://accounts.google.com/o/oauth2/auth?access_type=offline'
    

    【讨论】:

      【解决方案3】:

      我自己也遇到了这个问题,在调试器中挖掘代码后发现,authorize_redirect 函数的任何额外关键字参数最终都会作为 url 上的参数,如果在此之前没有消耗它们。

      因此,解决问题的一个简单方法就是修改该调用

      return await oauth.google.authorize_redirect(request, redirect_uri, access_type="offline")
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-09-20
        • 2022-12-10
        • 2017-07-20
        • 2012-08-18
        • 2020-05-20
        • 1970-01-01
        • 2020-02-07
        • 1970-01-01
        相关资源
        最近更新 更多