ASP.Net Core, Angular2 and token based authentication

I'm writing a web application using ASP.NET core for the backend / Service and Angular2 as frontend and have Troubles with authentication / authorization.

In ASP.NET core I got just one html page&controller, HomeController with Index which allows anonymous Access ([AllowAnonymous]). This single page delivers the angular2-app to the Client.

All other communication is using ApiControllers (which in ASP.NET core are just normal Controllers, but the Actions on these Controllers expect and send JSON data. For authentication/authorization I want to use jwt tokens. Users, Roles, Claims etc. are stored in an IdentityDbContext using EF core.

Most tutorials I found are outdated, incomplete or refer to 3rd Party OAuth-solutions. I'm not looking for OAuth, I just want a page with username/Passwort and use Tokens to stay logged in since I'm using all API's to get data to and fro the backend. I read lots of tutorials, tried a few helpful libs, but still am confused about how to set up the Middleware chain for token-based security. As far as I understand I Need to add the Services for identity since I want to use IdentityDbContext:

public void ConfigureServices(IServiceCollection services)
{
  [...]
  services.AddIdentity<IdentityUserEntity, IdentityRoleEntity>()
    .AddEntityFrameworkStores<ApplicationDbContext, long>()
    .AddDefaultTokenProviders();
  [...]
}

But what Middleware do I Need to set up in Configure? Do I Need app.UseIdentity() or would app.UseJwtBearerAuthentication(o) enough? Wouldn't UseIdentity shortcut the authentication before the JwtBearer gets a shot at checking for Tokens??

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
  [...]
  app.UseIdentity();
  [...]
  app.UseJwtBearerAuthentication(jwtOptions);
  [...]
}

I ask because the Client automagically was authenticated after in my TokenController I performed a call to _signInManager.PasswordSignInAsync(...), even though my client did never receive the jwt. So somehow ASP.NET identity Management found some other way to identify my user after signing in, which of course should not happen.

// simplified controller
public class TokenController : Controller
{
  [HttpPost("[action]")]
  [AllowAnonymous]
  public async Task<JsonResult> Login([FromBody]LoginViewModel loginRequest)
  {
    var signin = await _signInManager.PasswordSignInAsync(loginRequest.Username, loginRequest.Passwort, true, true);
  }

  // this will work even though I don't handle any Tokens in the Client yet, so some other authentication mechanism is at work:
  [HttpGet("test")]
  [Authorize]
  public IActionResult Get()
  {
    return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
  }

} 

So how do I implement token based authentication and nothing else?

[UPDATE]

I'd guess I Need to intercept the Cookie authentication event and reject the principal to disable Cookie auth (see https://stackoverflow.com/a/38893778/7021): But for some reason my event handler never gets called.

  app.UseCookieAuthentication(new CookieAuthenticationOptions()
  {
    Events = new CookieAuthenticationEvents
    {
      OnValidatePrincipal = ValidateAsync
    }
  });

public static async Task ValidateAsync(CookieValidatePrincipalContext context)
{
  context.RejectPrincipal();
  await context.HttpContext.Authentication.SignOutAsync("BsCookie");
}

More good reads about auth, Cookies and token:
- http://andrewlock.net/exploring-the-cookieauthenticationmiddleware-in-asp-net-core/
- https://stormpath.com/blog/token-authentication-asp-net-core


MS has provided basic jwt token based authentication lib, you can see how to use it here:

https://code.msdn.microsoft.com/How-to-achieve-a-bearer-9448db57

In startup.cs, firstly config Jwt Beare

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        app.UseJwtBearerAuthentication(new JwtBearerOptions()
          {
              TokenValidationParameters = new TokenValidationParameters()
            {
                IssuerSigningKey = TokenAuthOption.Key,
                ValidAudience = TokenAuthOption.Audience,
                ValidIssuer = TokenAuthOption.Issuer,
                // When receiving a token, check that we've signed it.
                ValidateIssuerSigningKey = true,
                // When receiving a token, check that it is still valid.
                ValidateLifetime = true,
                // This defines the maximum allowable clock skew - i.e. provides a tolerance on the token expiry time 
                // when validating the lifetime. As we're creating the tokens locally and validating them on the same 
                // machines which should have synchronised time, this can be set to zero. Where external tokens are
                // used, some leeway here could be useful.
                ClockSkew = TimeSpan.FromMinutes(0)
            }
        });

Now you can add to services

    public void ConfigureServices(IServiceCollection services)
    {
         services.AddAuthorization(auth =>
          {
            auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
                .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme‌​)
                .RequireAuthenticatedUser().Build());
        });

Finally, use it in controller, simply add [Authorize("Bearer")]

   [Route("api/[controller]")]
   public class ValuesController : Controller
   {
      [HttpGet("GetStaff")]
      [Authorize("Bearer")]
       public IActionResult GetStaff()
      {
          List<string> model = new List<string>();
          foreach (User user in UserStorage.Users ){
           model.Add(user.Username);
          }
          return Json(model);
      }
    }

Check full details here: https://github.com/Longfld/ASPNETcoreAngularJWT

链接地址: http://www.djcxy.com/p/3818.html

上一篇: 使用OWIN载体令牌验证ASP.NET Core应用程序

下一篇: ASP.Net Core,Angular2和基于令牌的认证