如何在Web API 2中存储服务器端的承载令牌?

时间:2014-01-13 22:01:11

标签: authentication asp.net-web-api owin

我在Web API 2中设置了承载令牌身份验证,我不明白承载令牌在服务器端的存储方式(或在哪里)。以下是相关代码:

启动

public partial class Startup
{
    public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
    public static Func<UserManager<IdentityUser>> UserManagerFactory { get; set; }
    public static string PublicClientId { get; private set; }

    static Startup()
    {
        PublicClientId = "self";
        UserManagerFactory = () => new UserManager<IdentityUser>(new UserStore<IdentityUser>());
        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            TokenEndpointPath = new PathString("/Token"),
            Provider = new ApplicationOAuthProvider(PublicClientId, UserManagerFactory),
            AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
            AllowInsecureHttp = true
        };
    }

    public void ConfigureAuth(IAppBuilder app)
    {
        // Enable the application to use a cookie to store information for the signed in user
        app.UseCookieAuthentication(new CookieAuthenticationOptions());

        // Use a cookie to temporarily store information about a user logging in with a third party login provider
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        app.UseOAuthBearerTokens(OAuthOptions);
    }
}

WebApiConfig:

public class WebApiConfig
{
    public static void ConfigureWebApi()
    {
        Register(GlobalConfiguration.Configuration);
    }

    public static void Register(HttpConfiguration http)
    {
        AuthUtil.ConfigureWebApiToUseOnlyBearerTokenAuthentication(http);
        http.Routes.MapHttpRoute("ActionApi", "api/{controller}/{action}", new {action = Actions.Default});
    }
}

AuthUtil:

public class AuthUtil
{
    public static string Token(string email)
    {
        var identity = new ClaimsIdentity(Startup.OAuthOptions.AuthenticationType);
        identity.AddClaim(new Claim(ClaimTypes.Name, email));
        var ticket = new AuthenticationTicket(identity, new AuthenticationProperties());
        var currentUtc = new SystemClock().UtcNow;
        ticket.Properties.IssuedUtc = currentUtc;
        ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromMinutes(30));
        var token = Startup.OAuthOptions.AccessTokenFormat.Protect(ticket);
        return token;
    }

    public static void ConfigureWebApiToUseOnlyBearerTokenAuthentication(HttpConfiguration http)
    {
        http.SuppressDefaultHostAuthentication();
        http.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
    }
}

的LoginController:

public class LoginController : ApiController
{
    ...

    public HttpResponseMessage Post([FromBody] LoginJson loginJson)
    {
        HttpResponseMessage loginResponse;
        if (/* is valid login */)
        {
            var accessToken = AuthUtil.Token(loginJson.email);
            loginResponse = /* HTTP response including accessToken */;
        }
        else
        {
            loginResponse = /* HTTP response with error */;
        }
        return loginResponse;
    }
}

使用上面的代码,我可以登录并将持有者令牌客户端存储在cookie中,然后调用标有[Authorize]的控制器,然后让我进入。

我的问题是:

  1. 服务器端存储的承载令牌在哪里/如何?看起来这是通过其中一个OWIN调用来实现的,但我不知道在哪里。

  2. 是否可以将持有者令牌持久保存到数据库服务器端,以便在Web API服务器重启后它们可以保留在原位?

  3. 如果#2的答案为否,那么客户端是否仍然维护其持有者令牌并重新使用它,即使在Web API关闭并重新启动后也是如此?虽然这在生产中可能很少见,但经常会进行本地测试。

4 个答案:

答案 0 :(得分:85)

  1. 它们不是存储在服务器端 - 它们是发给客户端的,客户端在每次调用时都会显示它们。它们经过验证是因为它们是由owin主机的保护密钥签名的。在SystemWeb托管中,该保护密钥是web.config中的machineKey设置。

  2. 这是不必要的,只要owin主机使用的保护密钥在服务器重启时不会改变。

  3. 只要令牌有效,客户就可以持有令牌。

答案 1 :(得分:3)

对于那些正在寻找如何设置web.config的人来说,这是一个示例

<system.web>
<machineKey validation="HMACSHA256" validationKey="64-hex"
                 decryption="AES" decryptionKey="another-64-hex"/>
</system.web>

您需要使用validationKey和decriptionkey才能使其正常工作。

以下是如何生成密钥 https://msdn.microsoft.com/en-us/library/ms998288.aspx

答案 2 :(得分:2)

要添加此功能,可以使用CookieAuthenticationOptions的SessionStore属性将令牌保留在服务器端。我不会提倡这样做,但如果你的代币变得过大,那就在那里。

这是一个IAuthenticationSessionStore,因此您可以实现自己的存储介质。

答案 3 :(得分:0)

默认情况下,服务器不存储令牌。只有您的客户端拥有它,并通过授权标头将其发送到服务器。

如果您使用Visual Studio提供的默认模板,则在Startup ConfigureAuth方法中,以下IAppBuilder扩展名为:app.UseOAuthBearerTokens(OAuthOptions)。