src/WebJobs.Extensions.Http/Extensions/HttpRequestExtensions.cs (95 lines of code) (raw):

// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http.Headers; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; using System.Security.Claims; using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; namespace Microsoft.Azure.WebJobs.Extensions.Http { public static class HttpRequestExtensions { private const int DefaultBufferSize = 1024; private const string EasyAuthIdentityHeader = "x-ms-client-principal"; // Shared serializer instance. This is safe for multi-threaded use. private static readonly Lazy<DataContractJsonSerializer> EasyAuthClaimsIdentitySerializer = new Lazy<DataContractJsonSerializer>(GetClaimsIdentitySerializer<ClaimsIdentitySlim>); private static readonly Lazy<DataContractJsonSerializer> StaticWebAppsClaimsIdentitySerializer = new Lazy<DataContractJsonSerializer>(GetClaimsIdentitySerializer<StaticWebAppsClientPrincipal>); public static async Task<string> ReadAsStringAsync(this HttpRequest request) { request.EnableBuffering(); string result = null; using (var reader = new StreamReader( request.Body, encoding: Encoding.UTF8, detectEncodingFromByteOrderMarks: true, bufferSize: DefaultBufferSize, leaveOpen: true)) { result = await reader.ReadToEndAsync(); } request.Body.Seek(0, SeekOrigin.Begin); return result; } public static IDictionary<string, string> GetQueryParameterDictionary(this HttpRequest request) { // last one wins for any duplicate query parameters return request.Query.ToDictionary(p => p.Key, p => p.Value.Last()); } public static bool IsJsonContentType(this HttpRequest request) { return !string.IsNullOrEmpty(request.ContentType) && MediaTypeHeaderValue.TryParse(request.ContentType, out MediaTypeHeaderValue headerValue) && string.Equals(headerValue.MediaType, "application/json", StringComparison.OrdinalIgnoreCase); } public static ClaimsIdentity GetAppServiceIdentity(this HttpRequest request) { if (!request.Headers.ContainsKey(EasyAuthIdentityHeader)) { return null; } string headerValue = request.Headers[EasyAuthIdentityHeader].First(); if (TryConvertFromBase64EncodedJson<ClaimsIdentitySlim>(headerValue, EasyAuthClaimsIdentitySerializer.Value, out ClaimsIdentity claimsIdentity) || TryConvertFromBase64EncodedJson<StaticWebAppsClientPrincipal>(headerValue, StaticWebAppsClaimsIdentitySerializer.Value, out claimsIdentity)) { return claimsIdentity; } return null; } private static bool TryConvertFromBase64EncodedJson<T>( string payload, DataContractJsonSerializer serializer, out ClaimsIdentity claimsIdentity) where T : IIdentityPrincipal { claimsIdentity = null; using (var buffer = new MemoryStream(Convert.FromBase64String(payload))) { T deserializedPayLoad = default(T); try { deserializedPayLoad = (T)serializer.ReadObject(buffer); } catch (SerializationException) { return false; } if (deserializedPayLoad.Equals(default(T))) { return false; } claimsIdentity = deserializedPayLoad.ToClaimsIdentity(); return true; } } private static DataContractJsonSerializer GetClaimsIdentitySerializer<T>() { // This serializer has the exact same settings as used by EasyAuth to ensure compatibility var settings = new DataContractJsonSerializerSettings(); settings.UseSimpleDictionaryFormat = true; settings.DateTimeFormat = new DateTimeFormat("o"); return new DataContractJsonSerializer(typeof(T), settings); } } }