做业务时,”用户登录”这件事几乎绕不过去。自己写一套账号密码系统?又是加密、又是找回密码、又是防刷,光想想就头大。
更聪明的做法是:把身份认证外包给专业的身份提供商(IdP),自己只负责”拿到一个可信的用户身份”。这就是 OIDC(OpenID Connect)协议要解决的事。
今天这篇文章,我会带你用 Python 最好用的 OAuth/OIDC 库 —— Authlib,接入 Amazon Cognito,跑通一个完整的登录 / 回调 / 登出流程。
看完你会收获:
- OIDC 的核心概念(5 分钟讲明白)
- Cognito User Pool 的配置步骤(附截图要点)
- 一份可以直接跑的 Flask 示例代码
- 生产环境的 6 个避坑建议
文章字数比较多,建议先点个在看,收藏着慢慢看 👇
一、5 分钟搞懂 OIDC
如果你之前听过 OAuth 2.0,那 OIDC 可以理解为:
OIDC = OAuth 2.0 + 身份层(ID Token)
OAuth 2.0 解决的是”授权”(我允许第三方访问我的某些资源),OIDC 在它的基础上加了一个 id_token,专门用来告诉你”这个用户是谁”。
一次标准的 OIDC 登录流程是这样的:
1 | 用户 ──点击登录──▶ 你的应用 |
涉及的几个关键名词:
| 名词 | 作用 |
|---|---|
| Issuer | 身份提供商的地址,比如 Cognito 的 https://cognito-idp.us-east-1.amazonaws.com/{poolId} |
| Client ID / Secret | 你的应用在 IdP 那里的身份凭证 |
| Scope | 想要哪些信息,常用 openid email profile |
| id_token | 一个 JWT,里面装着用户的身份信息 |
| access_token | 用来调用受保护 API 的令牌 |
记住这几个词,下面的操作就不懵了。
二、Cognito User Pool 配置
Cognito 是 Amazon 家的托管身份服务,免费额度对中小项目非常友好(每月 50000 MAU 免费)。
1. 创建 User Pool
登录 Amazon Console → 搜索 Cognito → Create user pool,一路下一步,关注几个点:
- Sign-in options:勾选 Email(或手机号,看业务)
- Password policy:按需配置
- MFA:建议至少开启 Optional
- Self-service sign-up:如果允许用户自己注册就打开

2. 创建 App Client
User Pool 创建好之后,进入 Applications → App client ,选择刚刚创建的Client

- App type:建议选 Confidential client(服务端应用,能安全保存 secret)
- Authentication flows:勾
ALLOW_USER_SRP_AUTH和ALLOW_REFRESH_TOKEN_AUTH - Hosted UI settings(重点):
- Allowed callback URLs:
http://localhost:5000/auth/callback - Allowed sign-out URLs:
http://localhost:5000/ - OAuth 2.0 grant types:勾
Authorization code grant - OpenID Connect scopes:勾
openidemailprofile
- Allowed callback URLs:

3. 配置域名
在 Branding → Domain 里能够看到域名,比如这样子,这个和回调有关系,需要记住。
1 | https://my-demo.auth.us-east-1.amazoncognito.com |
4. 记下四样东西
配置完以后,把这四个值抄下来,马上要用:
1 | Region: us-east-1 |
三、开始写代码
1. 装依赖
1 | pip install authlib flask python-dotenv |
就这么简单,Authlib 把 OIDC 的脏活累活都封装好了。
2. 配置环境变量
新建 .env:
1 | FLASK_SECRET_KEY=随便一串随机字符串 |
3. 完整示例代码
新建 app.py:
1 | import os |
4. 跑起来
1 | python app.py |
浏览器打开 http://localhost:5000/,点击登录,跳到 Cognito 登录页,注册个账号,回跳后就能看到用户信息啦 🎉

四、这段代码里藏了多少”好东西”?
表面上就几十行,实际上 Authlib 替你默默做了这些事:
✅ 自动发现端点
server_metadata_url 指向 Discovery 文档,Authlib 自动解析出授权地址、token 地址、公钥地址……你完全不用手写。
✅ 自动校验 id_token
authorize_access_token() 内部会:
- 用 code 换 token
- 从
jwks_uri拉公钥 - 校验 id_token 的签名
- 校验
iss(签发者)是不是对的 - 校验
aud(受众)是不是你的 client_id - 校验
exp(过期时间) - 校验
nonce(防重放)
任何一步出错都会抛异常,你不需要手写 JWT 解析。
✅ 自动启用 PKCE
code_challenge_method: S256 开启 PKCE,有效防止授权码被劫持。这是 OAuth 2.1 的推荐做法。
✅ 自动管理 state 和 nonce
state 防 CSRF,nonce 防重放,都写到 session 里了,你不用操心。
五、生产环境避坑指南
Demo 能跑不代表能上线,下面这 6 个点请务必注意:
1️⃣ 一定要用 HTTPS
回调地址必须是 https://,session cookie 记得加上 Secure 和 HttpOnly:
1 | app.config.update( |
2️⃣ Secret 不要写死在代码里
用 Amazon Secrets Manager 或 Parameter Store 读取,千万别提交到 Git。
3️⃣ 用户 ID 请用 sub,不要用 email
email 可能被用户改掉,sub 是 Cognito 生成的稳定唯一 ID,把它作为你数据库里的用户主键。
4️⃣ session 别放进程内存
多实例部署时,state / nonce 会丢。改用 Redis 存 session:
1 | pip install flask-session redis |
5️⃣ 登出要调 Cognito 的 /logout
只清本地 session 没用,Cognito Hosted UI 还有自己的 cookie,用户下次点登录会直接免密进来。一定要跳转到 Cognito 的 /logout。
6️⃣ 再做一次业务层校验
拿到 id_token 后,除了 Authlib 的标准校验,最好再确认 token_use == "id"(Cognito 特有字段),避免把 access_token 当 id_token 用。
六、常见报错速查
| 报错信息 | 原因 |
|---|---|
redirect_mismatch | 回调地址跟 App client 里配的对不上(末尾斜杠、http/https 都要一致) |
invalid_client | secret 错了,或 Public client 不该发 secret |
nonce 校验失败 | Flask session 没持久化,重启后就丢了 |
id_token 签名错误 | Region 或 Pool ID 配错,导致 issuer 不匹配 |
七、扩展阅读
- Authlib 官方文档:https://docs.authlib.org/
- Cognito 开发者指南:https://docs.aws.amazon.com/cognito/
- OIDC 协议规范:https://openid.net/connect/
写在最后
OIDC 本质上就两件事:拿到一个可信的 id_token、校验它。Authlib 把这两件事做到了极致简洁,10 行代码就能接入任何符合 OIDC 标准的身份提供商 —— Cognito、Auth0、Keycloak、Okta、Google、微信开放平台…… 换一个 IdP,只要换 Discovery URL 就行。
如果这篇文章对你有帮助,欢迎点赞 + 在看 + 转发,让更多同行少踩坑 🙏
下一篇想看什么?留言告诉我:
- ① FastAPI 版 OIDC 接入
- ② 纯 API 服务如何校验 Bearer Token
- ③ Cognito 对接Auth0等第三方登录
我们下期见 👋
关注我,一起把后端写得又快又稳。


