问题
I am using web api for accessing data and I want to authenticate and authorize web api.For that I am using JWT token authentication. But I have no idea where should I store access tokens?
What I want to do?
1)After login store the token
2)if user want to access any method of web api, check the token is valid for this user,if valid then give access.
I know two ways
1)using cookies
2)sql server database
which one is the better way to store tokens from above?
回答1:
Alternatively, if you just wanted to authenticate using JWT the implementation would be slightly different
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.Events = new JwtBearerEvents
{
OnTokenValidated = context =>
{
var user = context.Principal.Identity.Name;
//Grab the http context user and validate the things you need to
//if you are not satisfied with the validation fail the request using the below commented code
//context.Fail("Unauthorized");
//otherwise succeed the request
return Task.CompletedTask;
}
};
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey("MyVeryStrongKeyHiddenFromAnyone"),
ValidateIssuer = false,
ValidateAudience = false
};
});
still applying use authentication before use MVC.
[Please note these are very simplified examples and you may need to tighten your security more and implement best practices such as using strong keys, loading configs perhaps from the environment etc]
Then the actual authentication action, say perhaps in AuthenticationController would be something like
[Route("api/[controller]")]
[Authorize]
public class AuthenticationController : Controller
{
[HttpPost("authenticate")]
[AllowAnonymous]
public async Task<IActionResult> AuthenticateAsync([FromBody]LoginRequest loginRequest)
{
//LoginRequest may have any number of fields expected .i.e. username and password
//validate user credentials and if they fail return
//return Unauthorized();
var claimsIdentity = new ClaimsIdentity(new Claim[]
{
//add relevant user claims if any
}, "Cookies");
var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
await Request.HttpContext.SignInAsync("Cookies", claimsPrincipal);
return Ok();
}
}
}
in this instance I'm using cookies so I'm returning an HTTP result with Set Cookie. If I was using JWT, I'd return something like
[HttpPost("authenticate")]
public IActionResult Authenticate([FromBody]LoginRequest loginRequest)
{
//validate user credentials and if they validation failed return a similar response to below
//return NotFound();
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes("MySecurelyInjectedAsymKey");
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
//add my users claims etc
}),
Expires = DateTime.UtcNow.AddDays(1),//configure your token lifespan and needed
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey("MyVerySecureSecreteKey"), SecurityAlgorithms.HmacSha256Signature),
Issuer = "YourOrganizationOrUniqueKey",
IssuedAt = DateTime.UtcNow
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var tokenString = tokenHandler.WriteToken(token);
var cookieOptions = new CookieOptions();
cookieOptions.Expires = DateTimeOffset.UtcNow.AddHours(4);//you can set this to a suitable timeframe for your situation
cookieOptions.Domain = Request.Host.Value;
cookieOptions.Path = "/";
Response.Cookies.Append("jwt", tokenString, cookieOptions);
return Ok();
}
I hope these helps
回答2:
I'm not familiar with storing your users tokens on your back end app, I'll quickly check how does that work however if you are using dotnet core to authenticate with either cookies or with jwt, from my understanding and experience you need not store anything on your side.
If you are using cookies then you just need to to configure middleware to validate the validity of a cookie if it comes present in the users / consumer's headers and if not available or has expired or can't resolve it, you simply reject the request and the user won't even hit any of your protected Controllers and actions. Here's a very simplified approach with cookies.(I'm still in Development with it and haven't tested in production but it works perfectly fine locally for now using JS client and Postman)
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.Cookie.Name = "yourCookieName";
options.Cookie.SameSite = SameSiteMode.None;//its recommended but you can set it to any of the other 3 depending on your reqirements
options.Events = new Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationEvents
{
OnRedirectToLogin = redirectContext =>//this will be called if an unauthorized connection comes and you can do something similar to this or more
{
redirectContext.HttpContext.Response.StatusCode = 401;
return Task.CompletedTask;
},
OnValidatePrincipal = context => //if a call comes with a valid cookie, you can use this to do validations. in there you have access to the request and http context so you should have enough to work with
{
var userPrincipal = context.Principal;//I'm not doing anything with this right now but I could for instance validate if the user has the right privileges like claims etc
return Task.CompletedTask;
}
};
});
Obviously this would be placed or called in the ConfigureServices method of your startup to register authentication
and then in your Configure method of your Startup, you'd hookup Authentication like
app.UseAuthentication();
before
app.UseMvc()
来源:https://stackoverflow.com/questions/53455939/where-to-store-jwt-token-in-net-core-web-api