< Summary

Information
Class: ArturRios.Util.WebApi.Security.Extensions.HttpContextExtensions
Assembly: ArturRios.Util.WebApi
File(s): /home/runner/work/dotnet-webapi-util/dotnet-webapi-util/src/Security/Extensions/HttpContextExtensions.cs
Line coverage
95%
Covered lines: 20
Uncovered lines: 1
Coverable lines: 21
Total lines: 78
Line coverage: 95.2%
Branch coverage
83%
Covered branches: 15
Total branches: 18
Branch coverage: 83.3%
Method coverage
100%
Covered methods: 6
Fully covered methods: 5
Total methods: 6
Method coverage: 100%
Full method coverage: 83.3%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
GetUser(...)100%11100%
GetUser(...)100%11100%
ExtractToken(...)75%8890%
SetUser(...)100%11100%
TokenFromHeader(...)87.5%88100%
TokenFromCookie(...)100%22100%

File(s)

/home/runner/work/dotnet-webapi-util/dotnet-webapi-util/src/Security/Extensions/HttpContextExtensions.cs

#LineLine coverage
 1using System.Net.Http.Headers;
 2using ArturRios.Util.WebApi.Security.Constants;
 3using ArturRios.Util.WebApi.Security.Enums;
 4using ArturRios.Util.WebApi.Security.Interfaces;
 5using Microsoft.AspNetCore.Http;
 6
 7namespace ArturRios.Util.WebApi.Security.Extensions;
 8
 9/// <summary>Extension methods for reading the authentication token of the current request and the user attached
 10/// to it by <see cref="Middleware.AuthenticationMiddleware"/>.</summary>
 11public static class HttpContextExtensions
 12{
 13    private const string BearerScheme = "Bearer";
 14
 15    /// <param name="context">The current HTTP context.</param>
 16    extension(HttpContext context)
 17    {
 18        /// <summary>Gets the authenticated user attached to the request.</summary>
 19        /// <returns>The authenticated user, or <see langword="null"/> if the request is not authenticated.</returns>
 20        public IAuthenticatedUser? GetUser() =>
 1121            context.Items[AuthenticationItemKeys.User] as IAuthenticatedUser;
 22
 23        /// <summary>Gets the authenticated user as the app's own identity type.</summary>
 24        /// <typeparam name="TUser">The app's identity type.</typeparam>
 25        /// <returns>The authenticated user, or <see langword="null"/> if the request is not authenticated or the
 26        /// attached user is of another type.</returns>
 27        public TUser? GetUser<TUser>() where TUser : class, IAuthenticatedUser =>
 428            context.Items[AuthenticationItemKeys.User] as TUser;
 29
 30        /// <summary>Extracts the raw authentication token from the <c>Authorization: Bearer</c> header, the named
 31        /// cookie, or either (header first).</summary>
 32        /// <param name="source">Where to read the token from.</param>
 33        /// <param name="cookieName">The cookie name used when <paramref name="source"/> is <see cref="TokenSource.Cooki
 34        /// or <see cref="TokenSource.Either"/>.</param>
 35        /// <returns>The token, or <see cref="string.Empty"/> when none is found.</returns>
 36        public string ExtractToken(TokenSource source, string cookieName)
 37        {
 2338            ArgumentNullException.ThrowIfNull(context);
 39
 2340            return source switch
 2341            {
 1642                TokenSource.Header => TokenFromHeader(context),
 443                TokenSource.Cookie => TokenFromCookie(context, cookieName),
 344                TokenSource.Either => TokenFromHeader(context) is { Length: > 0 } header
 345                    ? header
 346                    : TokenFromCookie(context, cookieName),
 047                _ => string.Empty
 2348            };
 49        }
 50
 51        /// <summary>Attaches <paramref name="user"/> to the request, where <c>GetUser</c> and the authorization
 52        /// filters look for it.</summary>
 53        /// <param name="user">The authenticated user.</param>
 54        internal void SetUser(IAuthenticatedUser user) =>
 755            context.Items[AuthenticationItemKeys.User] = user;
 56    }
 57
 58    private static string TokenFromHeader(HttpContext context)
 59    {
 1960        var header = context.Request.Headers.Authorization.FirstOrDefault();
 61
 1962        if (string.IsNullOrWhiteSpace(header) || !AuthenticationHeaderValue.TryParse(header, out var parsed) ||
 1963            !string.Equals(parsed.Scheme, BearerScheme, StringComparison.OrdinalIgnoreCase) ||
 1964            string.IsNullOrWhiteSpace(parsed.Parameter))
 65        {
 866            return string.Empty;
 67        }
 68
 1169        return parsed.Parameter.Trim();
 70    }
 71
 72    private static string TokenFromCookie(HttpContext context, string cookieName)
 73    {
 674        var value = context.Request.Cookies[cookieName];
 75
 676        return string.IsNullOrWhiteSpace(value) ? string.Empty : value.Trim();
 77    }
 78}