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

桌面应用通过OAuth 2.0与Procore API认证时的HttpListener异常求助

解决Procore OAuth2桌面应用获取授权码时HttpListener异常问题

问题根源

你使用urn:ietf:wg:oauth:2.0:oob作为回调URI,这是带外(Out-of-Band)模式——Procore不会向你的应用发送HTTP回调请求,而是直接把授权码显示在浏览器页面上。但你的代码启动了HttpListener并等待GetContextAsync(),导致监听永远收不到请求,最终抛出异常。另外你还漏掉了HttpListener.Start()关键步骤,这也是触发异常的直接原因之一。

两种解决方案

方案1:改用本地HTTP回调(推荐,自动化程度高)

Procore支持本地HTTP回调,需要两步操作:

  1. 在Procore开发者后台注册你的回调URI(比如http://localhost:5000/callback)
  2. 修改代码,让HttpListener监听这个本地地址,同时更新授权请求中的redirect_uri参数

修改后的核心代码片段:

private async void button_Click(object sender, RoutedEventArgs e)
{
    string state = randomDataBase64url(32);

    // 配置本地回调URI和启动HttpListener
    string redirectURI = "http://localhost:5000/callback";
    var http = new HttpListener();
    http.Prefixes.Add(redirectURI + "/"); // 必须以斜杠结尾
    http.Start(); // 启动监听,原代码缺失这一步

    // 构造包含state和正确redirect_uri的授权请求
    string authorizationRequest = string.Format(
        "{0}?response_type=code&redirect_uri={1}&client_id={2}&state={3}",
        authorizationEndpoint,
        System.Uri.EscapeDataString(redirectURI),
        clientID,
        state);

    System.Diagnostics.Process.Start(authorizationRequest);

    // 现在能正常收到回调请求
    var context = await http.GetContextAsync();

    // 后续的响应处理、code验证、token交换逻辑保持不变...
}

方案2:适配带外模式(手动输入授权码)

如果不想修改回调URI,直接利用Procore在浏览器显示授权码的特性:

  1. 删除所有HttpListener相关代码
  2. 在应用中添加输入框,让用户复制浏览器中的授权码粘贴进来
  3. 用户输入完成后,调用performCodeExchange完成token交换

简化后的核心逻辑:

private void button_Click(object sender, RoutedEventArgs e)
{
    string state = randomDataBase64url(32);
    string redirectURI = "urn:ietf:wg:oauth:2.0:oob";

    string authorizationRequest = string.Format(
        "{0}?response_type=code&redirect_uri={1}&client_id={2}&state={3}",
        authorizationEndpoint,
        System.Uri.EscapeDataString(redirectURI),
        clientID,
        state);

    System.Diagnostics.Process.Start(authorizationRequest);

    // 弹出输入框让用户粘贴授权码
    string code = Microsoft.VisualBasic.Interaction.InputBox("请输入浏览器中的授权码:", "授权码输入");
    if (!string.IsNullOrEmpty(code))
    {
        performCodeExchange(code, redirectURI);
    }
}

额外注意点

  • 无论哪种方案,都要确保state参数正确传递并验证,防止CSRF攻击
  • 生产环境建议添加PKCE验证(你的代码提到了生成PKCE值但未使用,Procore支持该机制,能提升安全性)

内容的提问来源于stack exchange,提问作者RicEspn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 07:15:35