internal sealed class DcpTokenAuthenticationHandler()

in src/dotnet/AspireWorker/Authentication/DcpTokenAuthenticationHandler.cs [16:70]


internal sealed class DcpTokenAuthenticationHandler(
    IOptionsMonitor<AuthenticationSchemeOptions> options,
    ILoggerFactory logger,
    UrlEncoder encoder,
    IOptions<DcpSessionOptions> dcpOptions)
    : AuthenticationHandler<AuthenticationSchemeOptions>(options, logger, encoder)
{
    private const string BearerPrefix = "Bearer ";
    private const string PrincipalName = "dcp";
    private const string UnsupportedScheme = "Unsupported authorization scheme.";
    private const string MissingToken = "Missing token.";
    private const string InvalidToken = "Invalid token.";

    protected override Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        var authorization = Request.Headers.Authorization.ToString();
        if (string.IsNullOrEmpty(authorization))
        {
            Logger.LogInformation("Authorization header contained no usable value");
            return Task.FromResult(AuthenticateResult.NoResult());
        }

        if (!authorization.StartsWith(BearerPrefix, StringComparison.OrdinalIgnoreCase))
        {
            Logger.LogInformation("Unsupported authorization scheme");
            return Task.FromResult(AuthenticateResult.Fail(UnsupportedScheme));
        }

        var token = authorization[BearerPrefix.Length..].Trim();
        if (token.Length == 0)
        {
            Logger.LogWarning("Bearer token validation failed.");
            return Task.FromResult(AuthenticateResult.Fail(MissingToken));
        }

        if (!string.Equals(token, dcpOptions.Value.Token, StringComparison.Ordinal))
        {
            return Task.FromResult(AuthenticateResult.Fail(InvalidToken));
        }

        var identity = new ClaimsIdentity(Scheme.Name);
        identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, PrincipalName));
        var principal = new ClaimsPrincipal(identity);
        var ticket = new AuthenticationTicket(principal, Scheme.Name);

        return Task.FromResult(AuthenticateResult.Success(ticket));
    }

    protected override Task HandleChallengeAsync(AuthenticationProperties properties)
    {
        Response.StatusCode = StatusCodes.Status401Unauthorized;
        Response.Headers.Append("WWW-Authenticate", "Bearer");
        return Task.CompletedTask;
    }
}