0

I am running into an issue with trying to use .NET Identity with a MongoDB backend. The problem is related to authorization. I want the API to use JWT but it would seem the package I am using defaults to Cookies. The problem is that even when I try to turn off Cookies it fails. In other words I don't want the Mongo Identity handling incoming authorizations, I just want to take advantage of its backend user controls (failed logins, etc).

program.cs:

builder.Services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    }).AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ClockSkew = TimeSpan.FromMinutes(5),
                ValidIssuer = builder.Configuration["JwtSettings:Issuer"],
                ValidAudience = builder.Configuration["JwtSettings:Audience"],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["JwtSettings:Key"])),
    
                // This tells the framework how to interpret the role claim
                RoleClaimType = ClaimTypes.Role // or "role"
            };

        // Add detailed logging for authentication events
        options.Events = new JwtBearerEvents
        {
            OnAuthenticationFailed = context =>
            {
                Debug.WriteLine($"Authentication failed: {context.Exception.Message}");
                return Task.CompletedTask;
            },

            OnTokenValidated = context =>
            {
                var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<Program>>();
                foreach (var claim in context.Principal.Claims)
                {
                    Debug.WriteLine("Claim: {Type} = {Value}", claim.Type, claim.Value);
                }
                return Task.CompletedTask;
            },
            OnChallenge = context =>
            {
                Debug.WriteLine($"Authentication challenge: {context.Error}, {context.ErrorDescription}");
                return Task.CompletedTask;
            }
        };
    });

builder.Services.AddAuthorizationBuilder()
       .AddPolicy("AdminPolicy", policy => policy.RequireRole("Admin"))
       .AddPolicy("SuperAdminPolicy", policy => policy.RequireRole("SuperAdmin"))
       .AddPolicy("UserPolicy", policy => policy.RequireRole("User"));

// Setting up to user MS Identity for users and roles. This is unique because it is using MongoDB vs SQL Server
var mongoDbSettings = builder.Configuration.GetSection(nameof(MongoDBSettings)).Get<MongoDBSettings>();

builder.Services.AddIdentityMongoDbProvider<ApplicationUser, MongoRole>(identity =>
{
    identity.Password.RequiredLength = 8;
    identity.Password.RequireDigit = true;
    identity.Password.RequiredLength = 8;
    identity.Password.RequireNonAlphanumeric = true;
    identity.Password.RequireUppercase = true;
    identity.Password.RequireLowercase = true;

    // Lockout settings
    identity.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
    identity.Lockout.MaxFailedAccessAttempts = 20;

    // ApplicationUser settings
    identity.User.RequireUniqueEmail = false;
    identity.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#!%&*()^.-_";
},
    mongo =>
    {
        mongo.ConnectionString = mongoDbSettings?.IdentityConnectionString;
        mongo.UsersCollection = "Identity";
        mongo.RolesCollection = "Roles";
    }).AddDefaultTokenProviders();


builder.Services.Configure<IdentityOptions>(options =>
{
    options.SignIn.RequireConfirmedAccount = false;
});

builder.Services.ConfigureApplicationCookie(options =>
{
    // Disable cookie authentication
    options.Cookie.Name = "Disabled";
    options.ExpireTimeSpan = TimeSpan.Zero;
    options.SlidingExpiration = false;

    // Prevent redirects for APIs
    options.Events.OnRedirectToLogin = context =>
    {
        context.Response.StatusCode = StatusCodes.Status401Unauthorized;
        return Task.CompletedTask;
    };
    options.Events.OnRedirectToAccessDenied = context =>
    {
        context.Response.StatusCode = StatusCodes.Status403Forbidden;
        return Task.CompletedTask;
    };
});

Is there a way to stop cookie auth and instead use the JWT Auth, in API controller calls like this one:

[Authorize(Roles = "Admin,SuperAdmin")]
[HttpGet]
[Route("accounts")]
public ActionResult<AccountResult> Accounts(bool activeOnly)
{
    return _accountClient.GetAll(activeOnly);
}

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.