I can't get the simple Web Api authorized request via JWT in NET 7 minimal API from a MAUI client app (see below).
Therefore I thought of a workaround solution which looks like this:
- from the client side I also send the user data (user and password) for each request:
UserAuthentication user = new UserAuthentication(); user.UserName = "user1"; user.Email = "user1@email.com"; user.Password = "321"; HttpClient httpClient = new HttpClient(); var response = await httpClient.PostAsJsonAsync("https://api.mywebsite.com/api/data", user);
- in the minimal api, I then check the user details at the endpoint and then send the data back if the login matches.
app.MapPost("/api/data", [AllowAnonymous] (User user) =>. { if (user.UserName == "user1" && user.Password == "321") { return Results.Ok(list_data); } return Results.Unauthorized(); });
Two remarks:
- in the release version both user and password should be encrypted
- of course the user data comes from the DB, I hard-coded the user here for testing.
Can anyone confirm that I can implement an authorized request like this (i.e. without JWT)? Or have I missed something important here with my reasoning? The important thing is that it is at least as secure as with JWT.
Here again examples that do not work in MAUI Client (are already in other posts of mine). I'm starting to think there's a problem here at Microsoft, but don't know where best to report the problem (did it at ASP-NET-CORE, got rejected https://github.com/dotnet/AspNetCore.Docs/issues/27929 ).
minimal API (NET 7):
app.MapGet("/secret2", [Authorize] () => $"Hello You. This is a secret!!!");
MAUI CLient:
HttpClient httpClient = new HttpClient(); var requestMessage = new HttpRequestMessage { Method = HttpMethod.Get, RequestUri = new Uri(@"https://api.mysite.com/secret2") }; requestMessage.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); var response = await httpClient.SendAsync(requestMessage);
Although the same JWT works via Postman, here in MAUI I get an Unauthorized message 401 when requesting. I already posted details about this (also network protocol), see also github link.
Thanks
EDIT
According to Tiny Wang, the client code works. I then assume that there is an error in the JWT generation (wondering how the generated token then worked via Postman).
Here is the completely code from Web Api (for the generation and request of JWT, as well as endpoint for a request via JWT).).
using Microsoft.AspNetCore.Authorization; using Microsoft.IdentityModel.Tokens; using System.Security.Claims; using System.Text; using System.IdentityModel.Tokens.Jwt; using Microsoft.OpenApi.Models; using Microsoft.AspNetCore.Authentication.JwtBearer; namespace WebApplication1 { public class User { public string UserName { get; set; } = ""; public string Email { get; set; } = ""; public string Password { get; set; } = ""; public string AddInfo { get; set; } = ""; } public class Program { public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); builder.Services.AddAuthorization(); builder.Services.AddAuthentication().AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = false, ValidateAudience = false, ValidateLifetime = true, ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("superSecretKey@345")) }; }); builder.Services.AddEndpointsApiExplorer(); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.MapGet("/api/test", [AllowAnonymous] () => "Hello you!"); app.MapGet("/secret2", [Authorize] () => $"Hello You. This is a secret!!!"); app.MapPost("/security/createToken", [AllowAnonymous] (User user) => { if (user.UserName == "user" && user.Password == "123") { var claims = new[] { new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToString()), new Claim(JwtRegisteredClaimNames.GivenName, user.UserName), new Claim(JwtRegisteredClaimNames.Email, "user@test.com"), new Claim(ClaimTypes.Role, "Administrator"), new Claim("Role1", "Administrator"), new Claim("Role2", "Standard"), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) }; var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("superSecretKey@345")); var signinCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256); var tokeOptions = new JwtSecurityToken( issuer: "https://api.mysite.com:64591", audience: "https://api.mysite.com:64591", claims: claims, expires: DateTime.Now.AddMinutes(50), signingCredentials: signinCredentials ); var tokenString = new JwtSecurityTokenHandler().WriteToken(tokeOptions); return Results.Ok(tokenString); } return Results.Unauthorized(); }); app.UseHttpsRedirection(); app.Run(); } } }