Skip to content

Instantly share code, notes, and snippets.

@dj-nitehawk
Created February 24, 2024 06:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dj-nitehawk/ef1adfb23f248d936da6fea0ba025f09 to your computer and use it in GitHub Desktop.
Save dj-nitehawk/ef1adfb23f248d936da6fea0ba025f09 to your computer and use it in GitHub Desktop.
Basic Authentication With Swagger Support
public class BasicAuth(IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger,
UrlEncoder encoder)
: AuthenticationHandler<AuthenticationSchemeOptions>(options, logger, encoder)
{
internal const string SchemeName = "Basic";
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
if (IsPublicEndpoint() || !Request.Headers.ContainsKey("Authorization"))
return Task.FromResult(AuthenticateResult.NoResult());
var authHeader = Request.Headers.Authorization[0];
if (authHeader?.StartsWith(SchemeName) is true)
{
var token = authHeader[SchemeName.Length..].Trim();
var credentials = Encoding.UTF8.GetString(Convert.FromBase64String(token)).Split(':');
if (credentials[0] == "admin" && credentials[1] == "password")
{
var claims = new[]
{
new Claim("name", credentials[0]),
new Claim(ClaimTypes.Role, "Admin")
};
var identity = new ClaimsIdentity(claims, SchemeName);
var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, SchemeName);
return Task.FromResult(AuthenticateResult.Success(ticket));
}
Response.StatusCode = 401;
Response.Headers.Append("WWW-Authenticate", "Basic realm=\"website.com\"");
return Task.FromResult(AuthenticateResult.Fail("Invalid Authorization Header"));
}
Response.StatusCode = 401;
Response.Headers.Append("WWW-Authenticate", "Basic realm=\"website.com\"");
return Task.FromResult(AuthenticateResult.Fail("Invalid Authorization Header"));
}
bool IsPublicEndpoint()
=> Context.GetEndpoint()?.Metadata.OfType<AllowAnonymousAttribute>().Any() is null or true;
}
var bld = WebApplication.CreateBuilder();
bld.Services
.AddFastEndpoints()
.AddAuthorization()
.AddAuthentication(BasicAuth.SchemeName)
.AddScheme<AuthenticationSchemeOptions, BasicAuth>(BasicAuth.SchemeName, null);
bld.Services
.SwaggerDocument(
o =>
{
o.EnableJWTBearerAuth = false;
o.DocumentSettings = s =>
{
s.AddAuth(
BasicAuth.SchemeName,
new()
{
Name = "Authorization",
In = OpenApiSecurityApiKeyLocation.Header,
Type = OpenApiSecuritySchemeType.Basic
});
};
});
var app = bld.Build();
app.UseAuthentication()
.UseAuthorization()
.UseFastEndpoints()
.UseSwaggerGen();
app.Run();
[HttpGet("protected")]
sealed class MyEndpoint : EndpointWithoutRequest
{
public override async Task HandleAsync(CancellationToken c)
{
await SendAsync("you are allowed!");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment