Skip to content

Manual check valid token with ID4

Thang Chung edited this page Mar 16, 2019 · 1 revision
internal class AuthenticationMiddleware
{
    private readonly RequestDelegate _next;

    public AuthenticationMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context, IConfiguration config)
    {
        var displayUrl = context.Request.GetDisplayUrl().ToLower();

        if (displayUrl.Contains("/api/graphql"))
        {
            var authorizedKeyValue = context.Request.Headers.FirstOrDefault(k => k.Key.ToLowerInvariant() == "authorization");
            if (!string.IsNullOrEmpty(authorizedKeyValue.Value))
            {
                var authority = config["AuthN:Authority"];
                var audience = config["AuthN:Audience"];

                var token = authorizedKeyValue.Value.ToString();

                var client = new HttpClient();
                var disco = await client.GetDiscoveryDocumentAsync(authority);
                if (disco.IsError)
                {
                    throw new AuthenticationException($"Could not discovery the OAuth Server at {authority}");
                }

                var keys = new List<SecurityKey>();

                foreach (var webKey in disco.KeySet.Keys)
                {
                    var e = Base64Url.Decode(webKey.E);
                    var n = Base64Url.Decode(webKey.N);

                    var key = new RsaSecurityKey(new RSAParameters { Exponent = e, Modulus = n })
                    {
                        KeyId = webKey.Kid
                    };

                    keys.Add(key);
                }

                var parameters = new TokenValidationParameters
                {
                    ValidIssuer = disco.Issuer,
                    ValidAudience = audience,
                    IssuerSigningKeys = keys,

                    NameClaimType = JwtClaimTypes.Name,
                    RoleClaimType = JwtClaimTypes.Role,

                    RequireSignedTokens = true,
                    ValidateLifetime = true,
                    ValidateIssuer = false
                };

                var handler = new JwtSecurityTokenHandler();
                handler.InboundClaimTypeMap.Clear();

                var user = handler.ValidateToken(token.TrimStart("bearer").TrimStart(" "), parameters, out _);
                if (user != null)
                {
                    context.User = user; // for internal usage
                }
            }
        }

        await _next.Invoke(context);
    }
}