I am setting up bearer token authentication in Web API 2, and I don't understand how (or where) the bearer token is being stored server-side. Here is the relevant code:
Startup:
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; } }
Using the above code, I'm able to login and store the bearer token client-side in a cookie, and then make calls to controllers marked with [Authorize] and it lets me in.
My questions are:
Where / how is the bearer token being stored server-side? It seems like this is hapenning through one of the OWIN calls but I can't tell where.
Is it possible to persist the bearer tokens to a database server-side so that they can remain in place after a Web API server restart?
If the answer to #2 is no, is there anyway for a client to maintain its bearer token and re-use it even after the Web API goes down and comes back up? While this may be rare in Production, it can happen quite often doing local testing.
There are two patterns for client-side storage of bearer tokens: cookies and using HTML5 local storage. If cookies are being used to transmit the bearer token from client to server, then cookies would also be used to store the bearer token on the client side.
You use the bearer token to get a new Access token. To get an access token you send the Authentication server this bearer token along with your client id. This way the server knows that the application using the bearer token is the same application that the bearer token was created for.
To keep them secure, you should always store JWTs inside an httpOnly cookie. This is a special kind of cookie that's only sent in HTTP requests to the server.
By default the token is not stored by the server. Only your client has it and is sending it through the authorization header to the server. If you used the default template provided by Visual Studio, in the Startup ConfigureAuth method the following IAppBuilder extension is called: app.
They're not stored server side -- they're issued to the client and the client presents them on each call. They're verified because they're signed by the owin host's protection key. In SystemWeb hosting, that protection key is the machineKey setting from web.config.
That's unnecessary, as long as the protection key the owin host uses doesn't change across server restarts.
A client can hold onto a token for as long as the token is valid.
For those who are looking for how to set web.config, here is a sample
<system.web> <machineKey validation="HMACSHA256" validationKey="64-hex" decryption="AES" decryptionKey="another-64-hex"/> </system.web>
You need both validationKey and decriptionkey to make it work.
And here is how to generate keys https://msdn.microsoft.com/en-us/library/ms998288.aspx
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With