AWS Cognito 和 Flask 应用程序无法从 url 获取 jwt

Posted

技术标签:

【中文标题】AWS Cognito 和 Flask 应用程序无法从 url 获取 jwt【英文标题】:AWS Cognito & Flask app can't grab the jwt from the url 【发布时间】:2021-06-14 13:00:19 【问题描述】:

我有这个简单的 Flask 应用程序,当您访问登录页面时,它会将您重定向到您登录的 AWS Cognito 门户,然后您会重定向到 URL 中带有 jwt 的网页。我正在尝试从 url 获取 jwt,但没有运气。

一切正常,

我访问了应用程序(本地) 我被重定向到 AWS Cognito 门户 我登录并重定向到烧瓶应用程序 在那里我尝试获取 jwt 但没有运气

这是代码以及我目前尝试过的内容

from flask import Flask, render_template, redirect, request
app = Flask(__name__)

@app.route('/')
def landing_page():
    print('*' * 20)
    print(request.args)
    print(request.data.decode('UTF-8'))
    print(request.get_json())
    print(request.values)
    print(request.json)
    print(request.headers)
    print(request.headers.get('#id_token'))
    print(request.headers.get('id_token'))
    print(request.get_data().decode('UTF-8'))
    print(request.get_data())
    print(request.stream.read().decode('UTF-8'))
    print(request.args.get('id_token'))
    print(request.stream.read())
    print(request.args.to_dict([]))
    print(request.args.to_dict())
    print(request.args.get('id_token'))
    try:
        print(request.args['id_token'])
    except:
        print('pass')
    print('*' * 20)
    return redirect('https://xxx.auth.eu-central-1.amazoncognito.com/login?response_type=token&client_id=xxxxx&redirect_uri=http://localhost:5000/',
                    code=302)

结果

127.0.0.1 - - [17/Mar/2021 08:35:02] "GET / HTTP/1.1" 302 -
********************
ImmutableMultiDict([])

None
CombinedMultiDict([ImmutableMultiDict([]), ImmutableMultiDict([])])
None
Host: localhost:5000
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/xxxx Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Sec-Ch-Ua: "Google Chrome";v="89", "Chromium";v="89", ";Not A Brand";v="99"
Sec-Ch-Ua-Mobile: ?0
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Cookie: _xsrf=2|xxx|xxx|xxxx


None
None

b''

None
b''


pass
None
********************
127.0.0.1 - - [17/Mar/2021 08:35:05] "GET / HTTP/1.1" 302 -

【问题讨论】:

【参考方案1】:

Amazon Cognito 在重定向到您的应用程序时会在您的 URL 中设置 code 查询字符串。

例如,如果我将我的 Amazon Cognito 应用程序客户端重定向 URL 配置为 http://localhost:5000/cognito_redirect,我将拥有:

http://localhost:5000/cognito_redirect?code=bd5xxxxx-xxx5-xx1f-97xx-xxxxx3exxxx7

您可以从以下 URL 中检索它:

@app.route('/cognito_redirect')
def cognito_redirect():
  print(request.args.get('code'))

记录以下内容:

bd5xxxxx-xxx5-xx1f-97xx-xxxxx3exxxx7
127.0.0.1 - - [19/Mar/2021 23:23:02] "GET /cognito_redirect?code=bd5xxxxx-xxx5-xx1f-97xx-xxxxx3exxxx7 HTTP/1.1" 200 -

有关request 对象的更多详细信息,请参见Flask documentation。

2021-03-27 更新

大家好,我使用 AWS CloudFormation 为 Amazon Cognito 用户池创建了一个工作示例(明确显示您可以使用哪些配置)+ 一个具有单个路由的示例 Flask 应用程序

https://github.com/oieduardorabelo/2021-03-27-flask-with-cognito

您可以查看自述文件中的说明以了解如何部署它以及有关 Cognito 中 OAuth 重定向要求的一些详细信息。

这不是一份详尽的 Amazon Cognito 配置列表,还有更多配置方法,但它显示了使 OAuth 正常工作所需的最低要求。

我在这里确实有另一个使用 Node.js 的示例:

https://github.com/oieduardorabelo/node-amazon-cognito-oauth

【讨论】:

print(request.args.get('code')) 返回无,我的来自 cognito 的 url 查询重定向字符串也非常不同。但即使我为正确的响应调整了正确的参数,打印的值仍然是无。是否可以分享您项目的更多代码? 你是如何在 aws 上设置 cognito 的? 你能分享你得到的网址吗? @miquelvir 现在我没有确切的网址,但它类似于 'https://xxx.auth.eu-central-1.amazoncognito.com/login?response_type=token&client_id=xxxxx&redirect_uri=http://localhost:5000/#id_token=xxxxxx 和其他一些查询。我不知道他从哪里得到代码参数,在那个查询中没有任何类似代码的东西,甚至包括代码或类似的东西。 好吧,看到这个我已经提交了答案!【参考方案2】:

从发布的链接中,请注意您似乎感兴趣的 id_token 是 redirect_uri 的参数,而不是主 url 的参数。所以你需要获取redirect url,并解析它以从中获取id_token。

import urllib.parse as urlparse
from urllib.parse import parse_qs

@app.route('/')
def landing_page():
    try:
        redirect_url = request.args['redirect_uri']
        print(redirect_url)
        parsed = urlparse.urlparse(redirect_url)
        id_token = parse_qs(parsed.query)['id_token']
        print(id_token)
    except:
        print('pass')
    return redirect('https://xxx.auth.eu-central-1.amazoncognito.com/login?response_type=token&client_id=xxxxx&redirect_uri=http://localhost:5000/',
                    code=302)

【讨论】:

我没有收到错误,我正在通过。我也试过#id_token,但还是一样 因为有错误,你得到了通过,尝试删除 except 看看你有什么错误 错误请求浏览器(或代理)发送了一个此服务器无法理解的请求。 请提供完整的堆栈跟踪 没有堆栈跟踪,我只是在网络浏览器和烧瓶应用程序上收到了错误的请求127.0.0.1 - - [28/Mar/2021 16:35:07] "GET / HTTP/1.1" 400 - 127.0.0.1 - - [28/Mar/2021 16:35:07] "GET /favicon.ico HTTP/1.1" 404 -

以上是关于AWS Cognito 和 Flask 应用程序无法从 url 获取 jwt的主要内容,如果未能解决你的问题,请参考以下文章

AWS API Gateway Cognito 授权模拟

带有无服务器框架的 AWS cognito

使用 AWS Cognito 和 AD FS 作为 Web 应用程序的身份验证

使用 aws-cognito-identity-js 时获取的类型错误

Cognito 用户池作为具有客户端凭据的身份提供者仅在保存到 aws 控制台后才有效

AWS + Serverless - 如何获取 cognito 用户池生成的密钥