2

I am trying to use JwtBearerAuthentication in Asp core 2.0 and I've encountered two main issues.

The Configure method of startup is like this:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
            {
                HotModuleReplacement = true
            });
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseTestSensitiveConfiguration(null);

        app.UseStaticFiles();

        app.UseAuthentication();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");

            routes.MapSpaFallbackRoute(
                name: "spa-fallback",
                defaults: new { controller = "Home", action = "Index" });
        });
    }

and the ConfigureServices like bellow:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc()
            .AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver())
            .AddJsonOptions(options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);

        services.AddDbContext<FGWAContext>(options => options.UseSqlServer(connection));

        services.AddIdentity<User, Role>()
            .AddEntityFrameworkStores<FGWAContext>()
            .AddDefaultTokenProviders();

        services.Configure<IdentityOptions>(options =>
        {
            // Password settings
            options.Password.RequireDigit = false;
            options.Password.RequiredLength = 4;
            options.Password.RequireNonAlphanumeric = false;
            options.Password.RequireUppercase = false;
            options.Password.RequireLowercase = false;

            // Lockout settings
            options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
            options.Lockout.MaxFailedAccessAttempts = 10;

            // User settings
            options.User.RequireUniqueEmail = true;
        });



        //// If you want to tweak Identity cookies, they're no longer part of IdentityOptions.
        //services.ConfigureApplicationCookie(options => options.LoginPath = "/Account/LogIn");
        //services.AddAuthentication();
        //// If you don't want the cookie to be automatically authenticated and assigned to HttpContext.User, 
        //// remove the CookieAuthenticationDefaults.AuthenticationScheme parameter passed to AddAuthentication.
        //services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        //    .AddCookie(options =>
        //    {
        //        options.LoginPath = "/Account/LogIn";
        //        options.LogoutPath = "/Account/LogOff";
        //    });
        //services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        //    .AddJwtBearer(jwtBearerOptions =>
        //    {
        //        //jwtBearerOptions.Events.OnChallenge = context =>
        //        //{
        //        //    context.Response.Headers["Location"] = context.Request.Path.Value;
        //        //    context.Response.StatusCode = 401;
        //        //    return Task.CompletedTask;
        //        //};
        //        jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters
        //        {
        //            ValidateIssuerSigningKey = true,
        //            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your secret goes here")),

        //            ValidateIssuer = true,
        //            ValidIssuer = "The name of the issuer",

        //            ValidateAudience = true,
        //            ValidAudience = "The name of the audience",

        //            ValidateLifetime = true, //validate the expiration and not before values in the token

        //            ClockSkew = TimeSpan.FromMinutes(5) //5 minute tolerance for the expiration date
        //        };
        //    });

        // Enable Dual Authentication 
        services.AddAuthentication()
          .AddCookie(cfg => cfg.SlidingExpiration = true)
          .AddJwtBearer(cfg =>
          {
              cfg.RequireHttpsMetadata = false;
              cfg.SaveToken = true;

              cfg.TokenValidationParameters = new TokenValidationParameters()
              {
                  ValidIssuer = Configuration["Tokens:Issuer"],
                  ValidAudience = Configuration["Tokens:Issuer"],
                  IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Tokens:Key"]))
              };

          });

        services.AddTransient<IModelsService, ModelsService>();
        services.AddTransient<IRestaurantService, RestaurantService>();
    }

and the two main issues:

1- It does not work! I call the method to generate token http://localhost:59699/api/accountapi/login the the answer is something like this:

{"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJmb29kdGVzdGdldHVzckBnbWFpbC5jb20iLCJqdGkiOiIyZGQ0MDhkNy02NDE4LTQ2MGItYTUxYi1hNTYzN2Q0YWYyYzgiLCJpYXQiOiIxMC8xMi8yMDE3IDM6NDA6MDYgQU0iLCJuYmYiOjE1MDc3Nzk2MDYsImV4cCI6MTUwNzc3OTkwNiwiaXNzIjoiRXhhbXBsZUlzc3VlciIsImF1ZCI6IkV4YW1wbGVBdWRpZW5jZSJ9.of-kTEIG8bOoPfyCQjuP7s6Zm32yFFPlW_T61OT8Hqs","expires_in":300}

then I call the protected resource this way:

sending config

but the protected resource is not accessible.

2- After failure to authenticate, it redirects the request to login page. How can I disable this auto challenge behavior?

before you start answering I have to tell that, I have tried https://wildermuth.com/2017/08/19/Two-AuthorizationSchemes-in-ASP-NET-Core-2 to craete the authentication and this https://learn.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x too; and also this ASP.NET Core 2.0 disable automatic challenge to disable auto challenge, but non of them worked.

Update

The desired config is to use jwtbearerauthentication on webapi calls and for the others use cookie. Then while using the former I want to return not authorized (401) response on a not authorized request while for the later one I want a redirection.

halfer
  • 19,824
  • 17
  • 99
  • 186
ConductedClever
  • 4,175
  • 2
  • 35
  • 69

1 Answers1

2

I see at least one error. Your Authorization header should be "Bearer TOKEN", not "bearer". So capitalize Bearer.

Then for the redirection of the api call. Put the Authorize attribute with the JwtBearer schema on the api actions:

[Route("api/method")]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[HttpGet]
public IActionResult MyApiCall()
{
 .....
}
Bogdan S
  • 21
  • 2