Django基于OIDC对接Keycloak实现SSO时回调找不到会话oidc_states
OIDC对接Keycloak触发会话状态丢失异常排查
异常根因
这个SuspiciousOperation报错,本质是发起认证时存在服务端会话里的oidc_states值,在Keycloak回调请求到达时,找不到对应的存储会话。结合你提供的配置和日志,问题按实际影响优先级从高到低排序如下:
- 中间件重复注册SessionMiddleware
你贴的MIDDLEWARE列表里,django.contrib.sessions.middleware.SessionMiddleware共出现两次:一次在安全中间件之后,一次在SessionRefresh配置之前。
重复加载会话中间件会导致单次请求处理过程中,两次初始化会话流程,每次初始化都会生成新的Session Key。最终浏览器接收到的Set-Cookie,对应最后一次生成的会话ID;而发起认证时存储state的会话属于更早生成的会话,两者ID完全不匹配,回调时自然无法读取到之前存储的oidc_states值。修正操作:删除重复的SessionMiddleware配置,保持该中间件仅注册一次,且位置在AuthMiddleware之前即可。
- OIDC路由前缀漏写结尾斜杠
你在根路由中配置的是path('oidc', include('keycloak_oidc.urls')),前缀没有添加结尾斜杠,会导致第三方库自带的路由路径被直接无分隔符拼接:
原本预期的/oidc/authenticate/、/oidc/callback/,被实际解析为/oidcauthenticate/、/oidccallback/,和你日志里记录的实际访问路径完全匹配。
这种拼接异常虽然能被Django的APPEND_SLASH自动逻辑兼容,但会导致会话Cookie的路径匹配出现偏差,也容易和Keycloak客户端配置的回调地址产生不一致。修正操作:将路由前缀修改为
path('oidc/', include('keycloak_oidc.urls')),添加结尾斜杠保证路径拼接逻辑正确。 - Keycloak客户端回调地址配置不匹配
确认Keycloak客户端设置的「有效重定向URI」,和修正路由后的实际回调路径完全一致:- 修正路由后的回调路径为
/oidc/callback/,不要和旧的/oidccallback/地址混用 - 确保回调地址的协议、域名、端口和Django服务实际运行的地址完全一致,避免跨域导致浏览器拦截会话Cookie
- 修正路由后的回调路径为
- 会话Cookie作用域被异常覆盖
你使用了from keycloak_oidc.default_settings import *的全量导入写法,需要检查该导入是否覆盖了默认的SESSION_COOKIE_PATH配置,保持该值为默认的/即可,避免回调路径不在Cookie的作用域范围内,导致浏览器发起回调请求时不携带会话Cookie。
其他日志问题说明
日志中出现的failed to get or create user: Claims verification failed,属于状态校验通过后的用户创建流程报错,和当前找不到oidc_states的异常属于两个独立流程节点:
- 该报错通常由两类原因导致:一是获取到的用户声明中缺少
preferred_username必填字段,二是token签名验证不通过,可在会话状态问题解决后单独排查对应配置。
内容的提问来源于stack exchange,提问作者Sumesh S.G
相关产品推荐
相关产品推荐

