FreeKit.Auth.Host OpenIddict 测试说明
本文档对应迁移后的独立认证服务 FreeKit.Auth.Host,用于验证 OpenIddict bootstrap、登录页、授权码流和 userinfo。
1. 当前实现边界
- 认证服务项目:
src/Services/Auth/FreeKit.Auth.Host - OpenIddict 端点:
/connect/authorize、/connect/token、/connect/userinfo - 当前端点走根路径,不再使用旧的
/identity_api/connect/* - 服务启动时会自动完成两类初始化:
- OpenIddict 表初始化
identity_connect_claim_mapping表和默认 claim 映射初始化
- 默认 bootstrap 客户端:
freekit.console、freekit.cmskit、freekit.im
2. 推荐本地测试方式
优先使用 Development 环境做 smoke test。
当前仓库里的本地 Development 配置:
- 服务地址:
https://localhost:7005 - 数据库:
localhost:3308 / freekit - 配置文件:
src/Services/Auth/FreeKit.Auth.Host/appsettings.Development.json
不建议默认使用 https-local-prod 做本地 smoke test,因为 LocalProduction 可能指向外部 MySQL。
启动命令
dotnet run --project src/Services/Auth/FreeKit.Auth.Host/FreeKit.Auth.Host.csproj --launch-profile https-dev
启动成功后,浏览器直接打开:
https://localhost:7005/connect/login
如果登录页能正常打开,说明基础路由已经对上。
3. 启动后数据库自检
3.1 Scope 校验
SELECT name, display_name, resources
FROM open_iddict_scope
WHERE name IN ('openid', 'profile', 'email', 'roles', 'console', 'cmskit', 'im')
ORDER BY name;
预期至少能看到:
openidprofileemailrolesconsole
3.2 Client 校验
SELECT client_id, display_name, redirect_uris, permissions, requirements
FROM open_iddict_application
WHERE client_id IN ('freekit.console', 'freekit.cmskit', 'freekit.im')
ORDER BY client_id;
本地最小 smoke test 重点看 freekit.console:
client_id = freekit.consoleredirect_uris包含https://localhost:7005/connect/test-callback- 开启 PKCE
3.3 Claim 映射校验
SELECT claim_type, user_property_name, source_type, is_enabled, sort_code
FROM identity_connect_claim_mapping
ORDER BY sort_code;
预期至少能看到:
sub -> Idname -> UserNameemail -> Emailrole -> UserRole
如果这个表不存在或为空,重启 FreeKit.Auth.Host 后会自动补齐。
4. 最小浏览器 Smoke Test
本地最简单的验证方式,是直接使用内置的 freekit.console 客户端和测试回调页。
固定 PKCE 参数
code_verifier:dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXkcode_challenge:E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
authorize 地址
https://localhost:7005/connect/authorize?client_id=freekit.console&response_type=code&scope=openid%20profile%20email%20roles%20console&redirect_uri=https://localhost:7005/connect/test-callback&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&code_challenge_method=S256&state=devflow
预期流程
- 未登录时跳到
https://localhost:7005/connect/login - 使用本地数据库里一个可登录账号完成登录
- 成功后会跳到
https://localhost:7005/connect/test-callback - 页面展示回调参数(code、state 等),并提供「用 Code 换 Token」按钮
- 点击按钮后,页面自动调用
/connect/token兑换 Token 并展示结果 - 可继续点击「UserInfo」按钮验证 token 有效性
/connect/test-callback 是内置的回调测试页面,由 ConnectController.TestCallback() 提供,用于本地 smoke test。前端 SPA 应使用自己的回调地址(如 {CmsKitClient}/auth/callback)。
5. Token 交换测试
把上一步拿到的 code 替换到下面命令里。
如果你想直接跑一键 smoke test,仓库里已经有脚本:
pwsh ./build/smoke_test_auth_openiddict.ps1 -UserName "你的账号" -Password "你的密码"
脚本会自动完成:
authorize- 登录提交
- callback 取
code /connect/token兑换 token
默认目标地址是 https://localhost:7005,默认客户端是 freekit.console。
curl 示例
curl.exe -k --request POST "https://localhost:7005/connect/token" \
--header "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=authorization_code" \
--data-urlencode "client_id=freekit.console" \
--data-urlencode "code=把这里替换成回调里的code" \
--data-urlencode "redirect_uri=https://localhost:7005/connect/test-callback" \
--data-urlencode "code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"
预期返回
{
"token_type": "Bearer",
"access_token": "...",
"expires_in": 3600,
"refresh_token": "..."
}
6. userinfo 测试
把 access_token 替换进去。
curl.exe -k --request GET "https://localhost:7005/connect/userinfo" \
--header "Authorization: Bearer 把这里替换成access_token"
预期返回用户 claims,例如:
{
"sub": "用户ID",
"name": "用户名",
"email": "邮箱",
"role": [
"Admin"
]
}
7. 如果你要联调前端客户端
除了内置 freekit.console,当前还预置了两个前端客户端:
freekit.cmskitfreekit.im
它们的回调地址来自:
Host.CmsKitClient
对应默认配置在:src/Services/Auth/FreeKit.Auth.Host/appsettings.json
如果你本地也启动了前端,可以把 authorize 里的参数切到对应 client:
client_id=freekit.cmskitscope=openid profile email roles cmskitredirect_uri={CmsKitClient}/auth/callback
但在纯后端 smoke test 阶段,优先建议先用 freekit.console。
8. 常见问题优先排查
8.1 /identity_api/connect/... 返回 request not found
这是旧路径。迁移后的 FreeKit.Auth.Host 要使用根路径:
- 正确:
/connect/authorize - 错误:
/identity_api/connect/authorize
8.2 登录成功后拿不到 code
优先检查:
redirect_uri是否和应用表里的配置完全一致client_id是否真的存在于open_iddict_applicationcode_challenge/code_verifier是否配对- 登录使用的账号是否真能登录,是否被锁定
8.3 /connect/token 返回 invalid_grant
优先检查:
code是否刚生成,是否已被消费过redirect_uri是否与 authorize 阶段完全一致code_verifier是否与 authorize 阶段匹配
8.4 本地突然连到了外部数据库
检查启动 profile。
本地 smoke test 建议固定使用:
https-dev
不要默认使用:
https-local-prod
8.5 claim 丢失或 userinfo 字段不全
先查:
SELECT claim_type, user_property_name, source_type, is_enabled, sort_code
FROM identity_connect_claim_mapping
ORDER BY sort_code;
如果表为空,重启服务后会自动回填默认映射。
9. 最小通过标准
满足下面四条,就可以认为迁移后的 OpenIddict 已基本可用:
https://localhost:7005/connect/login能正常打开open_iddict_scope、open_iddict_application、identity_connect_claim_mapping已自动初始化- 浏览器访问
authorize后能在test-callback页面拿到code /connect/token能成功换出access_token