在OpenIddict中向客户端应用传递OIDC第三方认证失败信息
场景与需求
我们基于.NET/C#和OpenIddict Server开发了认证服务器,通过OpenIddict Client对接第三方认证提供商(当前仅一个,后续会扩展)。正常登录流程运行正常:用户访问认证端点,选择第三方提供商,跳转至第三方站点完成认证,回调回我们的服务器后,我们获取令牌并将用户重定向到客户端应用的redirect_uri,同时附带授权码用于获取令牌。
但当第三方认证失败时,提供商将用户重定向到我们的回调URI并携带错误参数:https://id-server.example.com/identity/login/callback/{provider}?state={whatever}&error=access_denied&error_desciption=...,此时OpenIddict处理管道会返回400 BadRequest错误。我们希望改为将转换后的错误信息(error="access_denied",error_description="<Provider> authentication failed")携带正确的state参数,重定向到客户端的redirect_uri,完成完整流程跳转。
已完成的配置
已经在OpenIddict Client配置中添加错误处理器,让流程跳过OpenIddict的默认错误响应,进入自定义回调控制器处理:
options.AddEventHandler<OpenIddictClientEvents.ProcessErrorContext>(builder => { builder.UseInlineHandler(context => { if (context.RequestUri?.AbsolutePath.StartsWith("/identity/login/callback") ?? false) { // 交由控制器处理逻辑 context.SkipRequest(); } return default; }); });
当前疑问:回调控制器的错误处理逻辑
不清楚如何修改回调控制器的操作来检测并处理该错误,需要识别对应的客户端请求,携带正确的state重定向到客户端的redirect_uri。现有控制器代码片段:
[HttpGet("~/identity/login/callback/{provider}"), HttpPost("~/identity/login/callback/{provider}"), IgnoreAntiforgeryToken] public async Task<ActionResult> LogInCallback() { // 获取OpenIddict在回调处理中验证的授权数据 var result = await HttpContext.AuthenticateAsync(OpenIddictClientAspNetCoreDefaults.AuthenticationScheme); if (!result.Succeeded && result... <需要补充判断逻辑>)
正常登录流程梳理
- <客户端应用>
- <认证服务器>/identity/connect/authorize -- OIDC授权端点
- <认证服务器>/identity/account/login -- 本地登录页面,用户选择第三方认证提供商
- <认证服务器>/identity/account/externallogin -- 接收用户选择提供商的POST请求
- <第三方提供商>/authorize -- 第三方登录页面
- <认证服务器>/identity/login/callback/{provider} -- OpenIddict Client回调页面;此处会接收第三方返回的
error和error_description,随后从Cookie存储的认证属性中获取下一步URL - <认证服务器>/identity/account/externallogincallback?ReturnUrl=
-- 对应步骤2、3的登录端点 - <认证服务器>/identity/connect/authorize?redirect_uri=<客户端应用> -- 再次调用授权端点,此时用户已完成认证(可能会触发授权确认)
- <客户端应用>?code=... -- 客户端回调页面,正常流程下获取授权码;异常流程需返回转换后的错误信息
内容的提问来源于stack exchange,提问作者andrewf

