【问题标题】:How does Postman handle localhost OAuth 2 redirects?Postman 如何处理 localhost OAuth 2 重定向?
【发布时间】:2020-07-17 08:35:27
【问题描述】:

当使用 Postman 通过授权码获取访问令牌时,我需要输入的字段之一是 Callback URL,即向授权端点发出请求时的重定向 URI 查询参数。我了解此 URL 需要在 OAuth 提供程序中注册/列入白名单,但我的问题是邮递员在基于 localhost 时如何实际处理/拦截该请求/重定向回来?例如,如果我已经有一个在 http://locahost:8090 上运行的本地服务器,并且我告诉邮递员使用 http://localhost:8090 进行回调,邮递员最终如何看到该请求/重定向回来(到将身份验证代码交换为访问令牌)而不是我的本地 Web 服务器处理该请求?

【问题讨论】:

    标签: postman


    【解决方案1】:

    TL;DR: Postman 在处理响应时基本上会忽略回调 URL。

    长篇大论

    它确实需要它,但仅用于请求。正如您所说,它必须是正确的 - 与 IdP 客户端应用程序配置完全匹配 - 仅此而已。

    Postman 只是帮助您获取令牌,它不需要将其提供给消费应用程序,这是重定向 URL 的全部要点 - 客户端应用程序和 OAuth 客户端应用程序已知的静态路径确保邪恶的网站/中介不会通过滥用重定向流来窃取令牌。

    由于它不适用于 Internet 上的浏览​​器,因此 Postman 可以忽略重定向。一旦 IdP 使用令牌做出响应,就 Postman 而言,这很好。它可以将令牌保存在本地令牌存储中,并使用它来发出 API 请求。

    隐式流

    设置为从 Okta 端点获取令牌:

    当我点击“请求令牌”时,邮递员会发出这样的请求:

    GET https://exampleendpoint.okta.com/oauth2/default/v1/authorize?nonce=heythere&response_type=token&state=state&client_id={the_client_id}&scope=profile%20openid&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fimplicit%2Fcallback
    

    Postman 弹出浏览器以向 /authorize 端点发出此请求,然后 IdP 在该端点创建令牌(如果浏览器已有 cookie),或执行各种重定向以验证用户身份,然后创建令牌.

    在此流程结束时,Postman 将从包含令牌的 IdP 接收 302(在位置标头上)。该重定向的目标是 IdP 中配置的重定向 URL:

    302 
    Location: http://localhost:8080/implicit/callback#access_token=eyJraWQiOiJxOGRmTGczTERCX3BEVmk4YVBrd3JBc3AtMFU1cjB6cXRUMFJveFZRUVVjIiwiYWxnIjoiUlMyNTYifQ.{the_rest_of_the_token}&token_type=Bearer&expires_in=3600&scope=profile+openid&state=state
    

    此时 Postman 从 #access_token 参数中抓取令牌,就可以开始了。

    验证码流程

    Auth Code 流有 2 种风格:

    • 授权码(经典)
    • 授权码 + PKCE

    Auth Code 流程被认为比隐式流程“更好”,因为它需要流程中的第二步来获取访问令牌。您点击授权,它会为客户端提供代码,然后将代码交换为令牌。此令牌代码为服务器端组件提供了更多机会来做更多事情 - 额外检查、丰富令牌和各种其他事情。

    问:为什么会有 2 个 Auth Code 流程? 答:问题在于它需要一个服务器端组件,许多 SPA 和/或移动应用程序不想托管该组件。接收代码并获取令牌的端点必须维护凭据 - 客户端 ID 和客户端机密 - 这是 IdP 在创建令牌时需要的。 PKCE 是一个扩展,它消除了对受信任服务器的要求。它将计算的哈希添加到 IdP 记住的 /authorize 调用,然后在对 /token 的后续调用中,客户端提供哈希的源值。服务器执行相同的计算,检查它是否与原始请求中的相同,然后对它没有将令牌分发给坏人感到满意。

    使用 PKCE 验证代码

    就重定向而言,这与隐式完全相同。但是对于请求,它需要发出第二个请求来交换令牌的代码。这里的主要区别是

    • 访问令牌 URL,用于发送代码并获取令牌作为响应。
    • 代码质询和验证器,它们是生成和计算哈希的 PKCE 要求

    请求如下:

    1. GET 到 /authorize
    GET https://exampleendpoint.okta.com/oauth2/default/v1/authorize?nonce=heythere&response_type=code&state=state&client_id={client_id}&scope=profile%20openid&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fimplicit%2Fcallback&code_challenge=E7YtiHqJRuALiNL_Oc5MAtk5cesNh_mFkyaOge86KXg&code_challenge_method=S256
    

    Postman 将弹出浏览器(如果需要,IdP 将通过登录重定向它)

    最终的代码响应也是 302,但是 location 标头包含代码而不是标记:

    location: http://localhost:8080/implicit/callback?code=J3RlQqW122Bnnfm6W7uK&state=state
    

    所以现在客户端需要调用“Access Token URL”字段中定义的端点来获取令牌:

    POST https://exampleendpoint.okta.com/oauth2/default/v1/token
    Body:
    grant_type: "authorization_code"
    code: "J3RlQqW122Bnnfm6W7uK"
    redirect_uri: "http://localhost:8080/implicit/callback"
    code_verifier: "Fqu4tQwH6bBh_oLKE2zr0ijArUT1pfm1YwmKpg_MYqc"
    client_id: "{client_id}"
    client_secret: ""
    

    响应是一个很好的旧 200,不会重定向 - 授权调用将客户端发送回最终重定向登录页面,而 POST 只是一个正常的请求,响应上有令牌

    {"token_type":"Bearer","expires_in":3600,"access_token":"eyJraWQiOiJxOGRmTGczTERCX3BEVmk4YVBrd3JBc3AtMFU1cjB6cXRUMFJveFZRUVVjIiwiYWxnIjoiUlMyNTYifQ.*******","scope":"profile openid","id_token":"eyJraWQiOiJxOGRmTGczTERCX3BEVmk4YVBrd3JBc3AtMFU1cjB6cXRUMFJveFZRUVVjIiwiYWxnIjoiUlMyNTYifQ.********"}
    

    【讨论】:

    • 那么随着浏览器窗口 Postman 弹出,它有能力检测重定向发生吗?所以在授权码授予的情况下,它是否检测到将发生代码重定向,所以它停止它,从 URL 中获取代码,然后 Postman 直接交换代码 + 秘密以获得令牌?
    • 是的,这就是为什么它会弹出一个浏览器以获取隐式和身份验证代码流。它们需要完整的浏览器,因为 IdP 身份验证依赖于 Cookie,如果您没有说 Cookie,IdP 将启动浏览器重定向以完成身份验证。这一切都发生在初始 GET 到 /authorize 的上下文中。验证码略有不同,我将添加到答案中,因为我会在这里用完字符..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-26
    • 2014-08-16
    • 2019-11-10
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 2014-07-06
    相关资源
    最近更新 更多