This is a quick reference on how to create a custom token authentication.
For a simple demonstration, we will check the header of the request if it contains our token.
Warning! In real world, using plain text as your token is not the proper way to secure your application.
-
Create custom authentication scheme options and handler:
using Microsoft.AspNetCore.Authentication; public class MyAuthenticationOptions : AuthenticationSchemeOptions { public const string DefaultScheme = "MyAuthenticationScheme"; public string TokenHeaderName { get; set; } = "MyToken"; }
For authentication handler:
using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.Options; using System.Security.Claims; using System.Text.Encodings.Web; public class MyAuthenticationHandler : AuthenticationHandler<MyAuthenticationOptions> { public MyAuthenticationHandler (IOptionsMonitor<MyAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) { } protected override async Task<AuthenticateResult> HandleAuthenticateAsync() { //check header first if (!Request.Headers .ContainsKey(Options.TokenHeaderName)) { return AuthenticateResult.Fail($"Missing header: {Options.TokenHeaderName}"); } //get the header and validate string token = Request .Headers[Options.TokenHeaderName]!; //usually, this is where you decrypt a token and/or lookup a database. if(token!= "supersecretecode") { return AuthenticateResult .Fail($"Invalid token."); } //Success! Add details here that identifies the user var claims = new List<Claim>() { new Claim("FirstName", "Juan") }; var claimsIdentity = new ClaimsIdentity (claims, this.Scheme.Name); var claimsPrincipal = new ClaimsPrincipal (claimsIdentity); return AuthenticateResult.Success (new AuthenticationTicket(claimsPrincipal, this.Scheme.Name)); } }
-
Register the service in DI:
builder.Services.AddAuthentication (MyAuthenticationOptions.DefaultScheme) .AddScheme<MyAuthenticationOptions, MyAuthenticationHandler> (MyAuthenticationOptions.DefaultScheme, options => { });
This does the same thing as
AddJwtBearer
andAddCookie
, you can create an extension method if you like. -
Add authentication to the pipeline. Make sure it comes before authorization and endpoints.
app.UseAuthentication(); app.UseAuthorization(); app.MapControllers();
-
You can now set your endpoint to accept only authenticated users.
[Authorize] [ApiController] [Route("[controller]")] public class WeatherForecastController
You can also access the claims you set in your authentication handler via
User
in your controllers:
var claim = User.Claims.Where(c => c.Type == "FirstName").FirstOrDefault();
In other classes, you can inject
ClaimsPrincipal
to access the user. Register in DI where to get theClaimsPrincipal
when required:
builder.Services.AddHttpContextAccessor(); builder.Services.AddTransient<ClaimsPrincipal>(s => s.GetService<IHttpContextAccessor>().HttpContext.User);
Then in your class, add
ClaimsPrincipal
to your constructor:
public class MyService { public MyService(ClaimsPrincipal user) {
Top comments (0)