Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

first round of small perf updates #1089

Merged
merged 3 commits into from
Mar 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -110,15 +110,12 @@ internal static string? Issuer
throw new ArgumentNullException(nameof(headers));
}

string? idToken = null;
if (headers.ContainsKey(AppServicesAuthIdTokenHeader))
{
idToken = headers[AppServicesAuthIdTokenHeader];
}
headers.TryGetValue(AppServicesAuthIdTokenHeader, out var idToken);

#if DEBUG
if (string.IsNullOrEmpty(idToken))
{
idToken = AppServicesAuthenticationInformation.SimulateGetttingHeaderFromDebugEnvironmentVariable(AppServicesAuthIdTokenHeader);
idToken = SimulateGetttingHeaderFromDebugEnvironmentVariable(AppServicesAuthIdTokenHeader);
}
#endif
return idToken;
Expand All @@ -136,15 +133,11 @@ internal static string? Issuer
throw new ArgumentNullException(nameof(headers));
}

string? idp = null;
if (headers.ContainsKey(AppServicesAuthIdTokenHeader))
{
idp = headers[AppServicesAuthIdpTokenHeader];
}
headers.TryGetValue(AppServicesAuthIdpTokenHeader, out var idp);
#if DEBUG
if (string.IsNullOrEmpty(idp))
{
idp = AppServicesAuthenticationInformation.SimulateGetttingHeaderFromDebugEnvironmentVariable(AppServicesAuthIdpTokenHeader);
idp = SimulateGetttingHeaderFromDebugEnvironmentVariable(AppServicesAuthIdpTokenHeader);
}
#endif
return idp;
Expand All @@ -158,8 +151,8 @@ internal static string? Issuer
internal static ClaimsPrincipal? GetUser(IDictionary<string, StringValues> headers)
{
ClaimsPrincipal? claimsPrincipal;
string? idToken = AppServicesAuthenticationInformation.GetIdToken(headers);
string? idp = AppServicesAuthenticationInformation.GetIdp(headers);
string? idToken = GetIdToken(headers);
string? idp = GetIdp(headers);
if (idToken != null && idp != null)
{
JsonWebToken jsonWebToken = new JsonWebToken(idToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,14 +161,29 @@ public async Task<AuthenticationResult> GetAuthenticationResultForUserAsync(
? DateTimeOffset.FromUnixTimeSeconds(long.Parse(expiration, CultureInfo.InvariantCulture))
: DateTimeOffset.Now;

string? displayName;
Account? account;
if (userClaims != null)
{
displayName = userClaims.GetDisplayName();
tenantId = userClaims.GetTenantId();
account = new Account(userClaims);
}
else
{
displayName = null;
tenantId = null;
account = null;
}

AuthenticationResult authenticationResult = new AuthenticationResult(
accessToken,
isExtendedLifeTimeToken: false,
userClaims?.GetDisplayName(),
displayName,
dateTimeOffset,
dateTimeOffset,
userClaims?.GetTenantId(),
userClaims != null ? new Account(userClaims) : null,
tenantId,
account,
idToken,
scopes,
tokenAcquisitionOptions != null ? tokenAcquisitionOptions.CorrelationId : Guid.Empty);
Expand Down
11 changes: 4 additions & 7 deletions src/Microsoft.Identity.Web/AuthorityHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,22 @@ internal static class AuthorityHelpers
internal static string BuildAuthority(MicrosoftIdentityOptions options)
{
Uri baseUri = new Uri(options.Instance);
string pathBase = baseUri.PathAndQuery.TrimEnd('/');
var domain = options.Domain;
var tenantId = options.TenantId;

if (options.IsB2C)
{
var userFlow = options.DefaultUserFlow;
return new Uri(baseUri, new PathString($"{pathBase}/{domain}/{userFlow}/v2.0")).ToString();
}
else
{
return new Uri(baseUri, new PathString($"{pathBase}/{tenantId}/v2.0")).ToString();
return new Uri(baseUri, new PathString($"{baseUri.PathAndQuery}{domain}/{userFlow}/v2.0")).ToString();
}

return new Uri(baseUri, new PathString($"{baseUri.PathAndQuery}{tenantId}/v2.0")).ToString();
}

internal static string EnsureAuthorityIsV2(string authority)
{
authority = authority.Trim().TrimEnd('/');
if (!authority.EndsWith("v2.0", StringComparison.InvariantCulture))
if (!authority.EndsWith("v2.0", StringComparison.Ordinal))
{
authority += "/v2.0";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public override void OnException(ExceptionContext context)
if (!string.IsNullOrWhiteSpace(ScopeKeySection))
{
// Load the injected IConfiguration
IConfiguration configuration = context.HttpContext.RequestServices.GetRequiredService<IConfiguration>();
IConfiguration? configuration = context.HttpContext.RequestServices.GetService<IConfiguration>();

if (configuration == null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,13 @@ public Task OnRedirectToIdentityProvider(RedirectContext context)
{
context.ProtocolMessage.ResponseType = OpenIdConnectResponseType.IdToken;
}
else if (Options.IsB2C)
{
context.ProtocolMessage.ResponseType = OpenIdConnectResponseType.CodeIdToken;
}
else
{
if (Options.IsB2C)
{
context.ProtocolMessage.ResponseType = OpenIdConnectResponseType.CodeIdToken;
}
else
{
context.ProtocolMessage.ResponseType = OpenIdConnectResponseType.Code;
}
context.ProtocolMessage.ResponseType = OpenIdConnectResponseType.Code;
}
}

Expand All @@ -65,14 +62,17 @@ public Task OnRemoteFailure(RemoteFailureContext context)
{
context.HandleResponse();

bool isOidcProtocolException = context.Failure is OpenIdConnectProtocolException;

// Handle the error code that Azure Active Directory B2C throws when trying to reset a password from the login page
// because password reset is not supported by a "sign-up or sign-in user flow".
// Below is a sample error message:
// 'access_denied', error_description: 'AADB2C90118: The user has forgotten their password.
// Correlation ID: f99deff4-f43b-43cc-b4e7-36141dbaf0a0
// Timestamp: 2018-03-05 02:49:35Z
// ', error_uri: 'error_uri is null'.
if (context.Failure is OpenIdConnectProtocolException && context.Failure.Message.Contains(ErrorCodes.B2CForgottenPassword))
string message = context.Failure?.Message ?? string.Empty;
if (isOidcProtocolException && message.Contains(ErrorCodes.B2CForgottenPassword))
{
// If the user clicked the reset password link, redirect to the reset password route
context.Response.Redirect($"{context.Request.PathBase}/MicrosoftIdentity/Account/ResetPassword/{SchemeName}");
Expand All @@ -84,13 +84,13 @@ public Task OnRemoteFailure(RemoteFailureContext context)
// Correlation ID: d01c8878-0732-4eb2-beb8-da82a57432e0
// Timestamp: 2018-03-05 02:56:49Z
// ', error_uri: 'error_uri is null'.
else if (context.Failure is OpenIdConnectProtocolException && context.Failure.Message.Contains(ErrorCodes.AccessDenied))
else if (isOidcProtocolException && message.Contains(ErrorCodes.AccessDenied))
{
context.Response.Redirect($"{context.Request.PathBase}/");
}
else
{
_errorAccessor.SetMessage(context.HttpContext, context.Failure?.Message);
_errorAccessor.SetMessage(context.HttpContext, message);

context.Response.Redirect($"{context.Request.PathBase}/MicrosoftIdentity/Account/Error");
}
Expand All @@ -102,11 +102,13 @@ private string BuildIssuerAddress(RedirectContext context, string? defaultUserFl
{
if (!_userFlowToIssuerAddress.TryGetValue(userFlow, out var issuerAddress))
{
_userFlowToIssuerAddress[userFlow] = context.ProtocolMessage.IssuerAddress.ToLowerInvariant()
issuerAddress = context.ProtocolMessage.IssuerAddress.ToLowerInvariant()
.Replace($"/{defaultUserFlow?.ToLowerInvariant()}/", $"/{userFlow.ToLowerInvariant()}/");

_userFlowToIssuerAddress[userFlow] = issuerAddress;
}

return _userFlowToIssuerAddress[userFlow];
return issuerAddress;
}
}
}
2 changes: 1 addition & 1 deletion src/Microsoft.Identity.Web/Base64UrlHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ internal static class Base64UrlHelpers
private const char Base64UrlCharacter63 = '_';
private static readonly Encoding TextEncoding = Encoding.UTF8;

private static readonly string DoubleBase64PadCharacter = string.Format(CultureInfo.InvariantCulture, "{0}{0}", Base64PadCharacter);
private static readonly string DoubleBase64PadCharacter = new string(Base64PadCharacter, 2);

// The following functions perform Base64URL encoding which differs from regular Base64 encoding:
// * Padding is skipped so the pad character '=' doesn't have to be percent encoded.
Expand Down
6 changes: 4 additions & 2 deletions src/Microsoft.Identity.Web/ClaimsPrincipalFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ public static class ClaimsPrincipalFactory
/// <code>
/// private async Task GetChangedMessagesAsync(IEnumerable&lt;Notification&gt; notifications)
/// {
/// HttpContext.User = ClaimsPrincipalExtension.FromTenantIdAndObjectId(subscription.TenantId,
/// subscription.UserId);
/// foreach (var notification in notifications)
/// {
/// SubscriptionStore subscription =
/// subscriptionStore.GetSubscriptionInfo(notification.SubscriptionId);
/// HttpContext.User = ClaimsPrincipalExtension.FromTenantIdAndObjectId(subscription.TenantId,
/// subscription.UserId);
/// string accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(scopes);
/// ...}
/// }
/// </code>
/// </example>
public static ClaimsPrincipal FromTenantIdAndObjectId(string tenantId, string objectId)
Expand Down
4 changes: 2 additions & 2 deletions src/Microsoft.Identity.Web/ClientInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ namespace Microsoft.Identity.Web
internal class ClientInfo
{
[JsonPropertyName(ClaimConstants.UniqueObjectIdentifier)]
public string UniqueObjectIdentifier { get; set; } = null!;
public string? UniqueObjectIdentifier { get; set; } = null;

[JsonPropertyName(ClaimConstants.UniqueTenantIdentifier)]
public string UniqueTenantIdentifier { get; set; } = null!;
public string? UniqueTenantIdentifier { get; set; } = null;

public static ClientInfo? CreateFromJson(string clientInfo)
{
Expand Down
6 changes: 4 additions & 2 deletions src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ internal static void WebAppCallsWebApiImplementation(
{
ClientInfo? clientInfoFromServer = ClientInfo.CreateFromJson(clientInfo);

if (clientInfoFromServer != null)
if (clientInfoFromServer != null && clientInfoFromServer.UniqueTenantIdentifier != null && clientInfoFromServer.UniqueObjectIdentifier != null)
{
context!.Principal!.Identities.FirstOrDefault()?.AddClaim(new Claim(ClaimConstants.UniqueTenantIdentifier, clientInfoFromServer.UniqueTenantIdentifier));
context!.Principal!.Identities.FirstOrDefault()?.AddClaim(new Claim(ClaimConstants.UniqueObjectIdentifier, clientInfoFromServer.UniqueObjectIdentifier));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -348,11 +348,11 @@ private static void AddMicrosoftIdentityWebAppInternal(
context.ProtocolMessage.SetParameter(Constants.TelemetryHeaderKey, IdHelper.CreateTelemetryInfo());

// Additional claims
if (context.Properties.Items.ContainsKey(OidcConstants.AdditionalClaims))
if (context.Properties.Items.TryGetValue(OidcConstants.AdditionalClaims, out var additionClaims))
{
context.ProtocolMessage.SetParameter(
OidcConstants.AdditionalClaims,
context.Properties.Items[OidcConstants.AdditionalClaims]);
additionClaims);
}

if (microsoftIdentityOptions.Value.IsB2C)
Expand Down