locked
Disable user authentication for a controller RRS feed

  • Question

  • User-1618242801 posted

    Hi,

    I want to disable user authentication for a controller. But I still need to authentication (bearer token should be valid) for this controller. And of course need authentication and user roles for other controllers. How can I disable role base auth for an controller/action?

    My startup class contains:

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
    app.UseAuthentication(); app.UseAuthorization(); app.UseRoleAbility();
    ...
    }


    And my controller contains 

    [Authorize]

    attribute.

    Monday, March 16, 2020 11:24 AM

All replies

  • User475983607 posted

    Just read the official docs.  Basically, add the authorize attribute and set the scheme to use.

    https://docs.microsoft.com/en-us/aspnet/core/security/authorization/limitingidentitybyscheme?view=aspnetcore-3.1

    Monday, March 16, 2020 11:28 AM
  • User-1618242801 posted

    I need Authentication for each action.

    app.UseAuthentication();
    app.UseAuthorization();
    

    They should be always run.

    Just I need to disable user credentials

    app.UseRoleAbility()

    for some actions. I'm not sure is it related with schema or how to use for this purpose.

    Monday, March 16, 2020 11:44 AM
  • User475983607 posted

    Please read the link in my first post! 

    It is up to you to configure all the authorization schemes the application uses.  Then apply the scheme to the controller or action using the authorize attribute as illustrated in the link.

    Monday, March 16, 2020 12:01 PM
  • User475983607 posted

    Also...

    I'm pretty sure you cannot have anonymous and JWT at the same time using the standard out-of-the-box security.  If that's what you are trying to do.  YIf you are trying to override anonymous then write custom code that detects if the JWT exists in the request. then apply JWT security over anonymous.   

    Monday, March 16, 2020 12:07 PM
  • User753101303 posted

    Hi,

    Unclear. Seems you are confusing authentication and checking roles ?  What does UseRoleAbility ? I never saw this yet and don't find much about that method. Could it be a method you wrote ?

    Monday, March 16, 2020 2:19 PM
  • User711641945 posted

    Hi Satellites,

    What is your  `app.UseRoleAbility();`?

    If you want one controller use jwt authentication only,it seems you just need use [Authorize] to your controller.For the other controllers,you want to use both role-based authentication and jwt authentication.You need to specify the policy like:`[Authorize(Policy = "RequireAdministratorRole")]`.

    Here is a working demo:

    1.UsersController:

    [Authorize]
    [ApiController]
    [Route("[controller]")]
    public class UsersController : ControllerBase
    {
        private IConfiguration _config;
            private List<User> users = new List<User>() {
            new User(){ Username="aa",Role="Student"},
            new User(){ Username="bb",Role="Administrator"}
            };
        public UsersController(IConfiguration config)
        {          
            _config = config;
        } 
       
    //test this method [HttpGet] public async Task<IActionResult> GetAll() { return Ok(); }

    //the following code is used to generate the jwt token [AllowAnonymous]//add this attribute to call it without authentication [HttpPost("Jwt")] public IActionResult Login([FromBody]User login) { IActionResult response = Unauthorized(); var user = AuthenticateUser(login); if (user != null) { var tokenString = GenerateJSONWebToken(user); response = Ok(new { token = tokenString }); } return response; } private string GenerateJSONWebToken(User userInfo) { var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"])); var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); var claim = new Claim[] { new Claim(ClaimTypes.Name, userInfo.Id.ToString()), new Claim(ClaimTypes.Role, userInfo.Role) }; var token = new JwtSecurityToken(_config["Jwt:Issuer"], _config["Jwt:Issuer"], claims: claim, expires: DateTime.Now.AddMinutes(120), signingCredentials: credentials); return new JwtSecurityTokenHandler().WriteToken(token); } private User AuthenticateUser(User login) { //check if the login user exsit var user = users.Where(u => u.Username == login.Username).FirstOrDefault(); return user; } }

    2.ValuesController:

    [Authorize(Policy = "RequireAdministratorRole")]
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        // GET api/values
    //test this method in the other controller [HttpGet] public ActionResult<IEnumerable<string>> Get() { return new string[] { "value1", "value2" }; } }

    3.Startup.cs:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc()               
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    
        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters()
            {
                ValidIssuer = Configuration["Jwt:Issuer"],
                ValidAudience = Configuration["Jwt:Issuer"],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"])),
    
                ValidateIssuerSigningKey = true,
                ValidateLifetime = true,
                RequireSignedTokens = true,
                ClockSkew = TimeSpan.FromMinutes(0)
            };
        });
        services.AddAuthorization(options =>
        {
            options.AddPolicy("RequireAdministratorRole",
                    policy => policy.RequireRole("Administrator"));
        });
    }
    
    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        //...
        app.UseDefaultFiles();
        app.UseStaticFiles();
        app.UseHttpsRedirection();
    
        app.UseAuthentication();
        app.UseAuthentication();
        app.UseMvc();
    }

    4.appSettings.json:

    "Jwt": {
        "Key": "ThisismySecretKey",
        "Issuer": "Test.com"
    }

    Result:

    If the user does not authenticate with Administrator role:

    If the user authenticate with Administrator role:

    Best Regards,

    Rena

    Tuesday, March 17, 2020 6:32 AM
  • User-1618242801 posted

    Thank you very much for your detail answer!

    app.UseRoleAbility() is a extension to create a user, check role etc.

    So, using "RequireAdministratorRole" is not a solution for me :(

    I think just I need to disable the line( app.UseRoleAbility() ) for some actions. I did some try with "app.UseWhen" but it did not work

    Wednesday, March 18, 2020 7:55 AM
  • User753101303 posted

    And it comes from which package or is this custom code ?

    For now my undestanding is that you don't want to disable user authentication but rather user authorization ie all authenticated users are required to be at least in a given role but for a particular controller it shouldn't be the case?

    If you really wanted to disable user authentication it would be https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.authorization.allowanonymousattribute?view=aspnetcore-3.1 but then on the next sentence it seems you tell this is notwhat you really want to do.

    It's easier to help if we can first fully understand what you are trying to do and at least for me, I find this still unclear. Can you confirm if you require all users to be in a given "public" role or at least one role, but that for a given controller users are allowed even if not in the "public" role (or any role at all ?). Also I"m trying to understand what does UseRoleAbility (show it maybe if this is custom code).

    If not, please try to rephrase what you are trying to as it does NOT seem to be disable user authentication.

    Wednesday, March 18, 2020 11:04 AM
  • User711641945 posted

    Hi Satellites,

    You could judge the controller name in you middleware:

    public async Task InvokeAsync(HttpContext context)
    {
        var path = context.Request.Path.Value;
        var item = path.Split("/");
        var controllerName = item[1];
        var flag = controllerName.ToLower().Contains("home");
        if (!flag)
        {
            //authenticate role..
            //do your stuff...
        }
    
        // Call the next delegate/middleware in the pipeline
        await _next(context);
    }

    Result:

    Best Regards,

    Rena

    Friday, March 20, 2020 2:14 AM