You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用OpenIdDict认证应用时无法获取授权码的问题

问题分析与解决

你的代码核心问题是完全搞错了授权码流程的调用逻辑,授权码流程不是直接POST授权端点就能拿到授权码的,它需要用户参与登录和授权,具体问题点和修正方案如下:

核心错误点

  • 请求方式错误:/connect/authorize授权端点需要用GET请求重定向用户,而不是直接POST。因为这个端点的作用是引导用户到授权服务器登录、确认授权,完成后服务器会把授权码通过你指定的redirect_uri回调回来。
  • 参数冗余错误:grant_type=code是令牌端点(/connect/token)的参数,授权端点不需要这个参数,你只需要传response_type=code即可。
  • 客户端认证方式冲突:同时用了Basic认证和参数里传client_secret,这完全没必要,而且授权端点通常不需要提前做客户端认证(机密客户端的话,在令牌交换阶段再做认证即可)。

正确的授权码流程实现步骤

步骤1:重定向用户到授权端点

在你的自研应用中,需要先把用户重定向到授权服务器的/connect/authorize端点,让用户完成登录和授权:

public IActionResult RedirectToAuthorization()
{
    var redirectUri = "https://localhost:7002/callback"; // 改成你自己的回调地址,不能用Swagger的跳转地址
    var state = Guid.NewGuid().ToString(); // 生成随机state,用于防CSRF

    // 构造授权端点的URL
    var authorizeUrl = $"https://localhost:7000/connect/authorize?client_id=web-client&response_type=code&redirect_uri={Uri.EscapeDataString(redirectUri)}&state={Uri.EscapeDataString(state)}";

    // 重定向用户到授权服务器
    return Redirect(authorizeUrl);
}

步骤2:处理授权服务器的回调,提取授权码

当用户完成登录授权后,授权服务器会把请求重定向到你指定的redirect_uri,并在URL参数里带上code(授权码)和state,你需要在回调接口里提取这个授权码:

public async Task<IActionResult> Callback(string code, string state)
{
    // 验证state(和之前生成的state对比,防止CSRF攻击)
    // 这里省略state验证逻辑,实际项目必须加

    // 用授权码交换令牌
    using var client = new HttpClient();
    var authorizationToken = Convert.ToBase64String(Encoding.UTF8.GetBytes($"web-client:901564A5-E7FE-42CB-B10D-61EF6A8F3654"));
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authorizationToken);

    var tokenParams = new Dictionary<string, string>
    {
        {"grant_type", "authorization_code"},
        {"code", code}, // 这里传入刚才拿到的授权码
        {"redirect_uri", "https://localhost:7002/callback"} // 必须和授权时的redirect_uri完全一致
    };

    var response = await client.PostAsync("https://localhost:7000/connect/token", new FormUrlEncodedContent(tokenParams));
    response.EnsureSuccessStatusCode();

    var tokenResponse = await response.Content.ReadFromJsonAsync<Dictionary<string, string>>();
    var accessToken = tokenResponse["access_token"];
    var refreshToken = tokenResponse["refresh_token"];

    // 这里可以把令牌保存起来,返回给前端或者自己使用
    return Ok(new { AccessToken = accessToken, RefreshToken = refreshToken });
}

关键说明

  • 你之前用Postman、Swagger能成功,是因为这些工具自动处理了重定向到授权服务器、引导用户登录、接收回调提取授权码的整个流程,而你的自研代码跳过了用户交互的环节,直接POST授权端点,自然拿不到授权码。
  • redirect_uri必须和你在OpenIdDict客户端配置里注册的地址完全一致,否则授权服务器会拒绝请求。

内容的提问来源于stack exchange,提问作者Linney E Dew II

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 20:38:31