| File: Provisioning\Internal\DefaultUserPrincipalProvider.cs | Web Access |
| Project: src\src\Aspire.Hosting.Azure\Aspire.Hosting.Azure.csproj (Aspire.Hosting.Azure) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Text.Json; using Azure.Core; namespace Aspire.Hosting.Azure.Provisioning.Internal; /// <summary> /// Default implementation of <see cref="IUserPrincipalProvider"/>. /// </summary> internal sealed class DefaultUserPrincipalProvider(ITokenCredentialProvider tokenCredentialProvider) : IUserPrincipalProvider { public async Task<UserPrincipal> GetUserPrincipalAsync(CancellationToken cancellationToken = default) { var credential = tokenCredentialProvider.TokenCredential; var response = await credential.GetTokenAsync(new(["https://graph.windows.net/.default"]), cancellationToken).ConfigureAwait(false); static UserPrincipal ParseToken(in AccessToken response) { // Parse the access token to get the user's object id (this is their principal id) var oid = string.Empty; var upn = string.Empty; var parts = response.Token.Split('.'); var part = parts[1]; var convertedToken = part.ToString().Replace('_', '/').Replace('-', '+'); switch (part.Length % 4) { case 2: convertedToken += "=="; break; case 3: convertedToken += "="; break; } var bytes = Convert.FromBase64String(convertedToken); Utf8JsonReader reader = new(bytes); while (reader.Read()) { if (reader.TokenType == JsonTokenType.PropertyName) { var header = reader.GetString(); if (header == "oid") { reader.Read(); oid = reader.GetString()!; if (!string.IsNullOrEmpty(upn)) { break; } } else if (header is "upn" or "email") { reader.Read(); upn = reader.GetString()!; if (!string.IsNullOrEmpty(oid)) { break; } } else { reader.Read(); } } } return new UserPrincipal(Guid.Parse(oid), upn); } return ParseToken(response); } }