【问题标题】:How to use dj-rest-auth with many clients如何与许多客户一起使用 dj-rest-auth
【发布时间】:2022-11-02 15:03:19
【问题描述】:

我想让许多不同的客户端能够访问我的 django 网站(更具体地说是它的 API),但我不确定如何使用 django-allauth、dj-rest-auth 和 simplejwt 来做到这一点。

我当前的客户端应用程序使用内置的 django 模板引擎,并使用 django-allauth 进行社交身份验证(Google 等)。它正在使用记录在案的安装建议。

我现在想创建不同类型的客户端不是使用 django 模板引擎(例如 Angular、Vue、flutter mobile 等),但我很困惑如何使用 dj-rest-auth 以便它可以扩展以支持任意数量的客户端类型。

以 Google 社交登录为例,当我创建一个新客户端时,我必须注册一个特定于该客户端的新 redirect_uri。

为了测试这一切,我创建了一个带有单个链接的简单烧瓶应用程序,以便我可以在将“代码/access_token”发送到我的 Django 应用程序之前检索它。该链接是使用以下内容创建的...

    var codeRequestUrl = 
`https://accounts.google.com/o/oauth2/v2/auth?\
scope=email&\
access_type=offline&\
include_granted_scopes=true&\
response_type=code&\
state=state_parameter_passthrough_value&\
redirect_uri=http%3A//127.0.0.1:5000/callback&\
client_id=${clientId}`;

...并在烧瓶中的“/回调”端点检索代码...

@app.route("/callback", methods=['GET'])
def redirect():
    code  = request.args.get('code', '')
    req = requests.post('http://127.0.0.1:8000/api/dj-rest-auth/google/', data={'code':code})
    return "done..."

...从那里我将 x-www-form-urlencoded POST 请求发送回根据其文档设置的 dj-rest-auth 端点...

class GoogleLogin(SocialLoginView):
    callback_url = 'http://127.0.0.1:5000/callback'
    adapter_class = GoogleOAuth2Adapter
    client_class = OAuth2Client

...
urlpatterns += [
    ...
    path('dj-rest-auth/google/', GoogleLogin.as_view(), name='google_login'),
    ....
]

Django 然后成功返回access_tokenrefresh_token 和一些关于登录用户的信息。

但这不是可以很好扩展的东西。如果我还要创建一个 Angular 客户端,我需要注册一个不同的回调(因为 Angular 客户端将在不同的端口和/或地址上运行,并且我还需要在 urls.py 中设置另一个路径并将其与可以处理不同 callback_url (redirect_uri) 的新 SocialLoginView 子类相关联。

考虑到这一切,我不知道如何使用颤振的移动应用程序来完成所有这些工作,据我所知,它没有 callback_url 的概念,所以我不确定如何发出 POST 请求考虑到我会立即收到redirect_uri_mismatch 错误,.../dj-rest-auth/google/ 甚至可以工作。

我是不是把它弄反了,在谷歌注册的客户端是 Angular、Vue、Flash 等应用程序?这意味着每个客户端都必须处理自己的 client_id 和 client_secret,这似乎绕过了 django-allauth 和 dj-rest-auth 的功能。

我觉得我误解了这一点,所以我真的很感激一些建议。

【问题讨论】:

    标签: django google-signin django-allauth dj-rest-auth


    【解决方案1】:

    我有足够的信心回答我自己的问题。 简而言之,是的,多个客户(包括第三方)是一个相当直接的过程。不幸的是,现有的许多博客文章和教程都采取了“第二方”客户端的视角,这确实使事情变得混乱。结果是很多与redirect_uri 相关的错误消息。

    值得称赞的是,他们的example Flask app 的 Google 文档正是我所需要的,但是有一些非常重要的观察结果,以及是什么让我如此困惑。

    首先,也是最重要的,回调 (redirect_uri) 是不是在 Django 中完全需要。在 Django 中,只需要这样的东西。

    from allauth.socialaccount.providers.oauth2.client import OAuth2Client
    from allauth.socialaccount.providers.google.views import GoogleOAuth2Adapter
    
    class GoogleLogin(SocialLoginView):
        adapter_class = GoogleOAuth2Adapter
        client_class = OAuth2Client
    
    urlpatterns += [
        ...
        path('auth/google/', GoogleLogin.as_view(), name='google_login'),
        ...
    ]
    

    所以回调属性是必需的。原因是 Flask(或第三方应用程序)处理全部Google 端的身份验证。

    第二个观察是 Flask 应用程序中的 redirect_uri 似乎必须是相同的为了两个都“code”请求步骤和“access_token”步骤。

    您可以在链接示例中看到它,其中 oauth2callback 函数(处理 redirect_uri),但我已经修改为与 dj-rest-auth 一起使用

    @app.route('/')
    def index():
      if 'credentials' not in flask.session:
        return flask.redirect(flask.url_for('oauth2callback'))
      credentials = json.loads(flask.session['credentials'])
      if credentials['expires_in'] <= 0:
        return flask.redirect(flask.url_for('oauth2callback'))
      else:
        data = {'access_token': credentials['access_token']}
        headers = headers = {'Content-Type': 'application/x-www-form-urlencoded'}
        r = requests.post(f'{URL_ROOT}/api/auth/google/', data=data, headers=headers)
        
        response_json = json.loads(r.text)
        access_token = response_json['access_token'] # JWT Access Token
        refresh_token = response_json['refresh_token']
        
        # Make a query to your Django website
        headers = headers = {'Authorization': f'Bearer {access_token}'}
        r = requests.post(f'{URL_ROOT}/api/object/{OBJECT_ID}/action/', data=data, headers=headers)
        # do stuff with r
    
    
    @app.route('/oauth2callback')
    def oauth2callback():
      if 'code' not in flask.request.args:
        auth_uri = ('https://accounts.google.com/o/oauth2/v2/auth?response_type=code'
                    '&client_id={}&redirect_uri={}&scope={}').format(CLIENT_ID, REDIRECT_URI, SCOPE)
        return flask.redirect(auth_uri)
      else:
        auth_code = flask.request.args.get('code')
        data = {'code': auth_code,
                'client_id': CLIENT_ID,
                'client_secret': CLIENT_SECRET,
                'redirect_uri': REDIRECT_URI,
                'grant_type': 'authorization_code'}
        r = requests.post('https://oauth2.googleapis.com/token', data=data)
        flask.session['credentials'] = r.text # This has the access_token
        return flask.redirect(flask.url_for('index'))
    

    所以总而言之,它有点像这样:

    • 在索引/主页上,用户按下指向/login 的“登录”html 锚点。
    • Flask 没有任何凭据,因此重定向到/oauth2callback 以开始身份验证。
    • 首先,使用 Google 的 GET /auth 端点和应用程序的客户端 ID 检索“代码”。
    • redirect_uri 确保代码流返回到自身,但是这一次,现在知道“代码”,使用您的应用程序的客户端 ID 和客户端密码向 Google 的 /token 端点发出 POST 请求。同样,redirect_uri 是相同的 (/oauth2callback)。
    • 现在谷歌的access_token 是已知的,Flask 应用程序重定向回 /index (尽管此时它可能在任何地方)
    • 回到 /index,Flask 应用程序现在具有 Google 的“access_token”。使用它登录您创建的 Django 的 dj-rest-auth 端点。
    • Django 然后将返回它的自己的access_token 和 refresh_token,所以根据需要继续使用它们。

    我希望这有帮助。

    请注意,您的烧瓶应用程序需要使用 Google 的 OAuth2 控制台注册为新的 Web 应用程序(因此它有自己的客户端 ID 和客户端密码)。换句话说,不要重用您可能已经使用现有的 Django allauth 实现创建的内容(这是我的场景)。每个第三方应用程序制造商都将处理自己的 OAuth2 凭据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-25
      • 2021-09-02
      • 2021-03-15
      • 2019-07-13
      相关资源
      最近更新 更多