using System; using System.Security.Claims; using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; namespace Umbraco.Extensions { public static class HttpContextExtensions { /// /// Try to get the basic auth username and password from the http context. /// public static bool TryGetBasicAuthCredentials(this HttpContext httpContext, out string username, out string password) { username = null; password = null; if ( httpContext.Request.Headers.TryGetValue("Authorization", out var authHeaders)) { var authHeader = authHeaders.ToString(); if (authHeader is not null && authHeader.StartsWith("Basic")) { //Extract credentials var encodedUsernamePassword = authHeader.Substring(6).Trim(); var encoding = Encoding.UTF8; var usernamePassword = encoding.GetString(Convert.FromBase64String(encodedUsernamePassword)); var seperatorIndex = usernamePassword.IndexOf(':'); username = usernamePassword.Substring(0, seperatorIndex); password = usernamePassword.Substring(seperatorIndex + 1); } return true; } return false; } /// /// Runs the authentication process /// public static async Task AuthenticateBackOfficeAsync(this HttpContext httpContext) { if (httpContext == null) { return AuthenticateResult.NoResult(); } var result = await httpContext.AuthenticateAsync(Cms.Core.Constants.Security.BackOfficeAuthenticationType); return result; } /// /// Get the value in the request form or query string for the key /// public static string GetRequestValue(this HttpContext context, string key) { HttpRequest request = context.Request; if (!request.HasFormContentType) { return request.Query[key]; } string value = request.Form[key]; return value ?? request.Query[key]; } public static void SetPrincipalForRequest(this HttpContext context, ClaimsPrincipal principal) { context.User = principal; } public static void SetReasonPhrase(this HttpContext httpContext, string reasonPhrase) { //TODO we should update this behavior, as HTTP2 do not have ReasonPhrase. Could as well be returned in body // https://github.com/aspnet/HttpAbstractions/issues/395 var httpResponseFeature = httpContext.Features.Get(); if (!(httpResponseFeature is null)) { httpResponseFeature.ReasonPhrase = reasonPhrase; } } /// /// This will return the current back office identity. /// /// /// /// Returns the current back office identity if an admin is authenticated otherwise null /// public static ClaimsIdentity GetCurrentIdentity(this HttpContext http) { if (http == null) throw new ArgumentNullException(nameof(http)); if (http.User == null) return null; //there's no user at all so no identity // If it's already a UmbracoBackOfficeIdentity var backOfficeIdentity = http.User.GetUmbracoIdentity(); if (backOfficeIdentity != null) return backOfficeIdentity; return null; } } }