如何存储访问令牌?(Oauth 2,Auth代码流程)

Bod*_*lot 10 security authentication oauth oauth-2.0

据我所知,授权代码流程的目的是为访问令牌交换auth代码.此交换发生在为页面和授权服务器提供服务的服务器之间,因此实际访问令牌不会暴露给客户端用户.

一旦获取了访问令牌,页面服务器应该如何存储?我正在从Pluralsight示例中学习,其中包含以下代码:

    public static HttpClient GetClient()
    {
        HttpClient client = new HttpClient();
        var accessToken = RequestAccessTokenAuthorizationCode();
        client.SetBearerToken(accessToken);

        client.BaseAddress = new Uri(IdentityConstants.API);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json"));

        return client;
    }

    private static string RequestAccessTokenAuthorizationCode()
    {
        // did we store the token before?
        var cookie = HttpContext.Current.Request.Cookies.Get("ClientMVCCookie.AuthCode");
        if (cookie != null && cookie["access_token"] != null && !string.IsNullOrEmpty(cookie["access_token"]))
        {
            return cookie["access_token"];
        }

        // no token found - request one

        // we'll pass through the URI we want to return to as state
        var state = HttpContext.Current.Request.Url.OriginalString;

        var authorizeRequest = new IdentityModel.Client.AuthorizeRequest(
            IdentityConstants.AuthEndoint);

        var url = authorizeRequest.CreateAuthorizeUrl(IdentityConstants.MVCClientSecret, "code", "management secret",
            IdentityConstants.MVCAuthCodeCallback, state);

        HttpContext.Current.Response.Redirect(url);

        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

这将导致每个请求检查cookie中是否存在访问令牌.如果不是,那么将启动流程.回调看起来像这样:

public class CallbackController : Controller
{
    // GET: STSCallback
    public async Task<ActionResult> Index()
    {
        // get the authorization code from the query string
        var authCode = Request.QueryString["code"];

        // with the auth code, we can request an access token.
        var client = new TokenClient(
            IdentityConstants.TokenEndoint,
            "mvc_client_auth_code",
             IdentityConstants.MVCClientSecretAuthCode);

        var tokenResponse = await client.RequestAuthorizationCodeAsync(
            authCode,
            IdentityConstants.MVCAuthCodeCallback);

        // we save the token in a cookie for use later on
        var cookie = Response.Cookies["ClientMVCCookie.AuthCode"];
        cookie.Expires = DateTime.Now.AddMinutes(1);
        cookie["access_token"] = tokenResponse.AccessToken;

        // get the state (uri to return to)
        var state = Request.QueryString["state"];

        // redirect to the URI saved in state
        return Redirect(state);
    }
}
Run Code Online (Sandbox Code Playgroud)

不将访问令牌存储在cookie中会导致授权代码流的整个目的失败吗?cookie将被传输到客户端浏览器,从而将其暴露给客户端?我错过了什么吗?这不是存储令牌的正确方法,应该如何存储?

Flo*_*ter 19

OAuth术语中的客户端是向资源服务器发出请求的组件,在您的情况下,客户端是Web应用程序的服务器(而不是浏览器).

因此,访问令牌应仅存储在Web应用程序服务器上.它不应该暴露给浏览器,也不需要,因为浏览器永远不会向资源服务器发出任何直接请求.它与Web应用程序服务器进行通信,而服务器服务器又使用访问令牌向资源服务器发出请求.

浏览器如何使用Web应用程序服务器对自身进行身份验证与OAuth 2.0无关.例如,它可能是常规会话cookie,Web应用程序服务器可能会将每个会话或每个用户与访问令牌相关联.

交换访问令牌的认证代码的令牌请求由web应用服务器完成,并且web应用服务器应该用授权服务器认证自己(例如,使用共享client_secret).

授权代码流确保客户端可以进行身份​​验证,从而防止冒充合法客户端的恶意客户端.并非所有Web应用程序客户端都具有服务器组件,并且在某些情况下,对资源服务器的请求是由浏览器中的JavaScript代码直接进行的.在这种情况下,浏览器是客户端,访问令牌必须由浏览器存储(在JavaScript变量,本地存储或cookie中).在这种情况下,客户端无法进行身份验证(但可以通过使用TLS和服务器仅重定向到已注册的端点URL来实现合理的安全性).

有关OAuth 2.0安全性的推荐读物:https://tools.ietf.org/html/rfc6819#section-4.3.3(RFC 6819)

  • 我完全理解那部分。我在问我在问题中包含的示例是否正确。该示例使用 ASP.NET MVC 服务器上的 cookie。我认为这个包含令牌的 cookie 会被传递给浏览器(会吗?),浏览器会暴露令牌。 (2认同)
  • @Mercury 至于cookie与会话:1)cookie只是如何进行前端到后端身份验证的一个示例。如果后端是OAuth客户端,这超出了OAuth的范围,这是我回答的要点。2)我不会争论cookie或令牌,而是向您指出这个http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/和这个计数器-位置:https://www.ducktypelabs.com/review-stop-using-jwt-for-sessions/。我们可能会提出的大多数论点都已经在其中涵盖了。我的看法是,两者都很好,各有利弊。 (2认同)

Flo*_*ter 6

cookie 永远不会暴露给浏览器。它是从授权服务器返回给客户端的响应的一部分,客户端本身是服务器,而不是浏览器。实现重定向端点CallbackController,从响应中提取 cookie。

cookie 永远不会传递到浏览器。示例代码中未显示浏览器如何通过客户端的应用程序服务器对自身进行身份验证,并且它不是 OAuth 的一部分。

授权服务器可以将令牌存储在请求正文中(例如,以 JSON 格式)而不是存储在 cookie 中。然而,这没有什么区别,因为客户端无论如何都可以看到并处理整个响应。

有关详细信息,请参阅我的另一个答案: https: //stackoverflow.com/a/44655679/2279059

旁注:CallbackController用于state存储将浏览器重定向到的最终 URL。这是非标准的,但有效。然而,state实际上是为了保护重定向端点免受 CSRF 攻击。它CallbackController不会验证state,而是盲目地重定向到给定的任何 URL。可能这个细节被省略了,因为代码只是作为示例。然而,它表明这段代码可能还没有完全适合生产。