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

时间:2017-06-02 08:19:23

标签: 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;
    }
}

这将导致每个请求检查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);
    }
}

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

3 个答案:

答案 0 :(得分:18)

客户端在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)

答案 1 :(得分:2)

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

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

授权服务器可以将令牌存储在请求主体中(例如,以JSON格式)而不是cookie中。但是,这没有任何区别,因为客户端无论如何都可以查看和处理整个响应。

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

附注:CallbackController使用state存储最终的网址以将浏览器重定向到。这是非标准的,但有效。但是,state实际上是为了保护重定向端点免受CSRF攻击。 CallbackController不会验证state,而是盲目地重定向到所提供的任何网址。可能这个细节被遗漏了,因为代码就是一个例子。但是,它表明此代码可能不完全是生产就绪的。

答案 2 :(得分:0)

如果要从浏览器请求剩余资源,则所需的流程为Implicit Grant。检查此Auth0帖子以决定流https://auth0.com/docs/api-auth/which-oauth-flow-to-use之间的关系。如果您想使用服务器上的访问令牌,则应该存储Authorization code并在每次需要时生成一个access tokenaccess token的预期寿命不超过5分钟,不需要存储