I'm building a web app (an authoritative server that will be used for a game I'm building) using ASP.NET Core 8, and I'm utilising Microsoft's Identity to do all authorisation and authentication.
Using Postman for testing Identity's AddIdentityApiEndpoints
endpoints I'm able to successfully login a registered user, which returns:
{
"tokenType": "Bearer",
"accessToken": "CfDJ8...",
"expiresIn": 3600,
"refreshToken": "CfDJ8..."
}
Using the accessToken
(I'm assuming this is what's required for the Bearer
token's value within Postman), I attempt to hit an endpoint that right now does nothing but the controller's behind an [Authorize]
tag. However I'm always getting 401 unauthorized.
Program.cs
:
public class Program
{
public static void Main(string[] args)
{
//CREATE WEBAPP BUILDER
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddIdentityApiEndpoints<IdentityUser>(options =>
{
options.Password.RequiredLength = 6;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireDigit = false;
options.Password.RequireUppercase = false;
options.Password.RequireLowercase = false;
})
// .AddRoles<IdentityRole>()
.AddEntityFrameworkStores<MM_DbContext>();
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
//options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = false,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["JwtSettings:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["JwtSettings:Key"]!))
};
});
// ADD SERVICES - DI ALLOWS TEST / NONTEST SERVICES
builder.Services
.AddScoped<Services.IArmouryService, Services.TestArmouryService>()
//.AddScoped<Services.IAuthenticationService, Services.TestAuthenticationService>()
.AddScoped<Services.IBattleboardService, Services.TestBattleboardService>()
.AddScoped<Services.ICharacterService, Services.TestCharacterService>()
.AddScoped<Services.IKingdomService, Services.TestKingdomService>()
.AddScoped<Services.ISoupkitchenService, Services.TestSoupkitchenService>()
.AddScoped<Services.ITreasuryService, Services.TestTreasuryService>();
// POSTGRESQL CONNECTION
builder.Services.AddDbContext<MM_DbContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("Db")));
System.Diagnostics.Debug.WriteLine($"Connection String: {builder.Configuration.GetConnectionString("Db")}");
// ADD CONTROLLERS
builder.Services.AddControllers().AddNewtonsoftJson(o => { });
// ADD SWASHBUCKLE/SWAGGER
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// NEW WEBAPP
var app = builder.Build();
app.MapIdentityApi<IdentityUser>();
// USE SWAGGER IF DEVELOPING
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
// MISC
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
// RUN
app.Run();
}
}
KingdomController
:
[Authorize]
[HttpPost("newmap")]
public async Task<ActionResult<IMapNewResponse>> NewMap([FromBody] MapNewPayload payload)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
try
{
var result = await _kingdomService.NewMap(payload);
if (result is IMapNewResponse)
{
return Ok(result);
}
else
{
return StatusCode(500, "Unexpected error occurred"); //incorrect error code - unsure how to handle
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"New map failed: {ex.Message}");
return StatusCode(500, "Internal server error");
}
}
I'm quite new to web servers and identity framework, as you can see in the code blocks I've submitted, I've already implemented a rudimentary Authentication system, but the time it would've taken me to iron out all of the features that Identity already provides out of the box just didn't seem worth it, I wanted to continue with developing the game, not an authentication/authorisation system.
I'm unsure what else to try or how to proceed.
I've got it working as following
Basically the token generated is for Identity.Bearer
builder.Services.AddAuthentication(options => {
options.DefaultAuthenticateScheme = IdentityConstants.BearerScheme;
options.DefaultChallengeScheme = IdentityConstants.BearerScheme;
options.DefaultScheme = IdentityConstants.BearerScheme;
}).AddBearerToken(IdentityConstants.BearerScheme);