Skip to main content

flask-pluginkit-oidc

基于 Authlib 的 OIDC Client,作为 Flask-PluginKit 插件使用,对接 staugur/passportd OIDC Provider。

依赖

  • Python >= 3.9
  • flask-pluginkit >= 3.11.0
  • authlib >= 1.7.0

快速开始

1. 安装

pip install flask-pluginkit-oidc
# 或从 Git 安装
pip install git+https://github.com/saintic/flask-pluginkit-oidc@master

2. 配置

通过环境变量或 app.config 设置以下配置:

配置项 环境变量 必填 说明
PASSPORTD_OIDC_CLIENT_ID PASSPORTD_OIDC_CLIENT_ID 是 OIDC Provider 分配的 client_id
PASSPORTD_OIDC_CLIENT_SECRET PASSPORTD_OIDC_CLIENT_SECRET 是 OIDC Provider 分配的 client_secret
PASSPORTD_OIDC_SERVER_METADATA_URL PASSPORTD_OIDC_SERVER_METADATA_URL 否 OIDC Discovery 端点,默认 https://passport.saintic.com/.well-known/openid-configuration
PASSPORTD_OIDC_CLIENT_KWARGS — 否 传递给 OAuth client 的额外参数,默认 {"scope": "openid profile"}
PASSPORTD_OIDC_STATE PASSPORTD_OIDC_STATE 否 插件启用状态,默认是enabled,禁用是disabled
PASSPORTD_OIDC_STATE_STORE PASSPORTD_OIDC_STATE_STORE 否 OAuth state 存储方式:session(默认,存客户端 session cookie)或 redis(存服务端 Redis)
PASSPORTD_OIDC_REDIS_URL PASSPORTD_OIDC_REDIS_URL 否 Redis 连接串,仅 STATE_STORE=redis 时使用,默认 redis://localhost:6379/0
PASSPORTD_OIDC_REDIS — 否 直接传入 Redis 客户端实例(优先级高于 REDIS_URL),仅 STATE_STORE=redis 时使用
PASSPORTD_OIDC_STATE_EXPIRES PASSPORTD_OIDC_STATE_EXPIRES 否 state 过期时间(秒),仅 STATE_STORE=redis 时使用,默认 3600

Authlib 约定:oauth.register(name="passportd_oidc") 会自动从 app.config 查找 PASSPORTD_OIDC_CLIENT_ID 和 PASSPORTD_OIDC_CLIENT_SECRET,无需手动传入。

3. 使用

from os import getenv
from flask import Flask, session, g, make_response, redirect
from flask_pluginkit import PluginManager

app = Flask(__name__)
app.secret_key = getenv("SECRET_KEY", "change-me")

app.config.update(
    PASSPORTD_OIDC_CLIENT_ID=getenv("PASSPORTD_OIDC_CLIENT_ID", ""),
    PASSPORTD_OIDC_CLIENT_SECRET=getenv("PASSPORTD_OIDC_CLIENT_SECRET", ""),
)

plugin = PluginManager(app, plugin_packages=["flask_pluginkit_oidc"])

def set_login_state(userinfo:dict):
    # 假设用session管理会话
    session["user"] = userinfo
    return make_response(redirect("/"))

@app.before_request
def before_request():
    # 强烈建议, 设置登录状态,如果返回 Flask.Response 对象, 扩展会直接 return 对象。
    g.set_login_state = set_login_state
    # 可选,登录后跳转地址
    g.login_redirect_url = "/"

if __name__ == "__main__":
    app.run(debug=True)

4. 测试

export PASSPORTD_OIDC_CLIENT_ID=your_client_id
export PASSPORTD_OIDC_CLIENT_SECRET=your_client_secret
python test_client.py

访问 http://localhost:5000/oauth2/passportd/login 发起 OIDC 登录。

5. userinfo

{
  "bio": "签名",
  "gender": 1,
  "location": "地点",
  "nickname": "昵称",
  "picture": "头像地址",
  "status": 1,
  "sub": "用户唯一标识UID"
}

6. 解决 OIDC state 丢失问题(可选)

Authlib 默认把 OAuth state(含 nonce、code_verifier)写入 Flask 客户端 session cookie。 部分浏览器(如 Brave)会阻止跨站 Cookie:用户从 Provider 授权页回调 /authorized 时, session cookie 丢失,Authlib 会抛出 MismatchingStateError(500)。

插件已内置兜底:即使 state 丢失也不会 500,而是重定向回登录页重新发起授权。

若要彻底规避该问题,可将 state 改为存到服务端 Redis:

app.config.update(
    PASSPORTD_OIDC_STATE_STORE="redis",
    PASSPORTD_OIDC_REDIS_URL=getenv("PASSPORTD_OIDC_REDIS_URL", "redis://localhost:6379/0"),
)
# 或者直接传入 Redis 客户端实例(需先 pip install redis)
# PASSPORTD_OIDC_REDIS=redis_client,

路由

路由 说明
/oauth2/passportd/login 发起 OIDC 授权,重定向至 Provider 登录页
/oauth2/passportd/authorized OIDC 回调地址,Provider 需配置为此 URL
/oauth2/passportd/profile 跳转到 OIDC Provider 的用户资料页

暴露 OIDC Server 信息

插件在 on_app_ready 时将共享信息挂到 app.extensions["flask_pluginkit_oidc"],外部模块 / 模板可直接复用:

# 外部模块中
oidc_meta = current_app.extensions["flask_pluginkit_oidc"]
oidc_meta["server_url"]   # OIDC Provider 的 issuer(discovery 文档中的签发地址),如 https://passport.saintic.com
oidc_meta["client"]       # Authlib OAuth 客户端实例

server_url 即 OIDC discovery 文档中的 issuer 字段(签发地址),仅当其是合法的 http/https URL 时才返回;插件在 on_app_ready 时加载一次,Authlib 会缓存 discovery 文档。

模板中也可通过 app.jinja_env.globals 自行挂载后使用。

跳转用户资料页

/oauth2/passportd/profile 视图直接重定向到 OIDC Provider 的 issuer(签发地址);若 issuer 非法或为空,则兜底跳转首页 /。

工作原理

  1. 插件通过 Flask-PluginKit 的 register() 入口加载,注册 Blueprint
  2. on_app_ready(app) 在应用完全就绪后调用(Flask-PluginKit >= 3.11.0),此时有应用上下文,安全地初始化 oauth.init_app(app) 并注册 OIDC 客户端;若配置 PASSPORTD_OIDC_STATE_STORE=redis,同时将 OAuth state 存储切换到 Redis
  3. 用户访问 /login → 重定向到 OIDC Provider 授权页
  4. Provider 认证后回调 /authorized → Authlib 完成 token 交换 + userinfo 获取;若 state 校验失败(如跨站 Cookie 被阻止),自动重定向回登录页而非 500
  5. userinfo 默认写入 session["user"] = userinfo 或通过 g.set_login_state(userinfo) 设置登录状态
  6. 重定向到 g.login_redirect_url 或 /

Metadata

Release files for flask-pluginkit-oidc 0.4.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for flask-pluginkit-oidc 0.4.2
File Size Uploaded
flask_pluginkit_oidc-0.4.2.tar.gz 8.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for flask-pluginkit-oidc 0.4.2
File Interpreter ABI Platform
flask_pluginkit_oidc-0.4.2-py3-none-any.whl Python 3 none any Details

Total release size: 16.9 kB

Release files / flask_pluginkit_oidc-0.4.2.tar.gz

Download URL flask_pluginkit_oidc-0.4.2.tar.gz
Size 8.2 kB
Tags Source
SHA-256 checksum
How to use checksums
1d2f66eeeb16162a2d06fbab726d9c8e15cbe063793db937d2ffc99de3e554a9
BLAKE2b-256 checksum
How to use checksums
f31b19645d4ab1599d3299faa6d644f7d9e17b36658882dda97d88e28dff17f6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.9

Release files / flask_pluginkit_oidc-0.4.2-py3-none-any.whl

Download URL flask_pluginkit_oidc-0.4.2-py3-none-any.whl
Size 8.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c6c1c43b0bdbdbfb9bf25deb9e2657bba417e09af306e2d1e3a3f74a59c0aafa
BLAKE2b-256 checksum
How to use checksums
9fcf422550925cf4f5d560553d4a4ee00a9e4a3f068234749482d95a58afb602
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.9

Release history Release notifications | RSS feed

This release

0.4.2 This release

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page