diff --git a/src/Microsoft.Identity.Web/AccountExtensions.cs b/src/Microsoft.Identity.Web/AccountExtensions.cs index fb5f8d93e..72f361354 100644 --- a/src/Microsoft.Identity.Web/AccountExtensions.cs +++ b/src/Microsoft.Identity.Web/AccountExtensions.cs @@ -17,7 +17,7 @@ public static class AccountExtensions /// /// The IAccount instance. /// A built from IAccount. - public static ClaimsPrincipal ToClaimsPrincipal(this IAccount account) + public static ClaimsPrincipal? ToClaimsPrincipal(this IAccount? account) { if (account != null) { diff --git a/src/Microsoft.Identity.Web/AuthorizeForScopesAttribute.cs b/src/Microsoft.Identity.Web/AuthorizeForScopesAttribute.cs index a128d33ab..05e60e89c 100644 --- a/src/Microsoft.Identity.Web/AuthorizeForScopesAttribute.cs +++ b/src/Microsoft.Identity.Web/AuthorizeForScopesAttribute.cs @@ -32,12 +32,12 @@ public class AuthorizeForScopesAttribute : ExceptionFilterAttribute /// /// Scopes to request. /// - public string[] Scopes { get; set; } + public string[]? Scopes { get; set; } /// /// Key section on the configuration file that holds the scope value. /// - public string ScopeKeySection { get; set; } + public string? ScopeKeySection { get; set; } /// /// Handles the MsalUiRequiredException. @@ -45,51 +45,47 @@ public class AuthorizeForScopesAttribute : ExceptionFilterAttribute /// Context provided by ASP.NET Core. public override void OnException(ExceptionContext context) { - // Do not re-use the attribute param Scopes. For more info: https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/issues/273 - string[] incrementalConsentScopes = Array.Empty(); - MsalUiRequiredException msalUiRequiredException = context.Exception as MsalUiRequiredException; + MsalUiRequiredException? msalUiRequiredException = + (context.Exception as MsalUiRequiredException) ?? + (context.Exception?.InnerException as MsalUiRequiredException); - if (msalUiRequiredException == null) + if (msalUiRequiredException != null && + CanBeSolvedByReSignInOfUser(msalUiRequiredException)) { - msalUiRequiredException = context.Exception?.InnerException as MsalUiRequiredException; - } + // the users cannot provide both scopes and ScopeKeySection at the same time + if (!string.IsNullOrWhiteSpace(ScopeKeySection) && Scopes != null && Scopes.Length > 0) + { + throw new InvalidOperationException($"Either provide the '{nameof(ScopeKeySection)}' or the '{nameof(Scopes)}' to the 'AuthorizeForScopes'."); + } - if (msalUiRequiredException != null) - { - if (CanBeSolvedByReSignInOfUser(msalUiRequiredException)) + // Do not re-use the attribute param Scopes. For more info: https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/issues/273 + string[]? incrementalConsentScopes; + + // If the user wishes us to pick the Scopes from a particular config setting. + if (!string.IsNullOrWhiteSpace(ScopeKeySection)) { - // the users cannot provide both scopes and ScopeKeySection at the same time - if (!string.IsNullOrWhiteSpace(ScopeKeySection) && Scopes != null && Scopes.Length > 0) - { - throw new InvalidOperationException($"Either provide the '{nameof(ScopeKeySection)}' or the '{nameof(Scopes)}' to the 'AuthorizeForScopes'."); - } + // Load the injected IConfiguration + IConfiguration configuration = context.HttpContext.RequestServices.GetRequiredService(); - // If the user wishes us to pick the Scopes from a particular config setting. - if (!string.IsNullOrWhiteSpace(ScopeKeySection)) + if (configuration == null) { - // Load the injected IConfiguration - IConfiguration configuration = context.HttpContext.RequestServices.GetRequiredService(); - - if (configuration == null) - { - throw new InvalidOperationException($"The {nameof(ScopeKeySection)} is provided but the IConfiguration instance is not present in the services collection"); - } + throw new InvalidOperationException($"The {nameof(ScopeKeySection)} is provided but the IConfiguration instance is not present in the services collection"); + } - incrementalConsentScopes = new string[] { configuration.GetValue(ScopeKeySection) }; + incrementalConsentScopes = new string[] { configuration.GetValue(ScopeKeySection) }; - if (Scopes != null && Scopes.Length > 0 && incrementalConsentScopes != null && incrementalConsentScopes.Length > 0) - { - throw new InvalidOperationException("no scopes provided in scopes..."); - } - } - else + if (Scopes != null && Scopes.Length > 0 && incrementalConsentScopes.Length > 0) { - incrementalConsentScopes = Scopes; + throw new InvalidOperationException("no scopes provided in scopes..."); } - - var properties = BuildAuthenticationPropertiesForIncrementalConsent(incrementalConsentScopes, msalUiRequiredException, context.HttpContext); - context.Result = new ChallengeResult(properties); } + else + { + incrementalConsentScopes = Scopes; + } + + var properties = BuildAuthenticationPropertiesForIncrementalConsent(incrementalConsentScopes, msalUiRequiredException, context.HttpContext); + context.Result = new ChallengeResult(properties); } base.OnException(context); @@ -114,7 +110,7 @@ private bool CanBeSolvedByReSignInOfUser(MsalUiRequiredException ex) /// current HTTP context in the pipeline. /// AuthenticationProperties. private AuthenticationProperties BuildAuthenticationPropertiesForIncrementalConsent( - string[] scopes, + string[]? scopes, MsalUiRequiredException ex, HttpContext context) { @@ -128,9 +124,13 @@ private AuthenticationProperties BuildAuthenticationPropertiesForIncrementalCons OidcConstants.ScopeProfile, }; + // TODO: scopes can actually be null here - how do we treat this case? + // if this is not allowed then we should throw before calling this method + // if this is allowed, we need to avoid the null ref below + properties.SetParameter>( OpenIdConnectParameterNames.Scope, - scopes.Union(additionalBuiltInScopes).ToList()); + scopes.Union(additionalBuiltInScopes).ToList()); // potential null ref exception // Attempts to set the login_hint to avoid the logged-in user to be presented with an account selection dialog var loginHint = context.User.GetLoginHint(); diff --git a/src/Microsoft.Identity.Web/Base64UrlHelpers.cs b/src/Microsoft.Identity.Web/Base64UrlHelpers.cs index cd7068860..28edb62ec 100644 --- a/src/Microsoft.Identity.Web/Base64UrlHelpers.cs +++ b/src/Microsoft.Identity.Web/Base64UrlHelpers.cs @@ -23,7 +23,7 @@ internal static class Base64UrlHelpers // * the 62nd and 63rd regular base64 encoding characters ('+' and '/') are replace with ('-' and '_') // The changes make the encoding alphabet file and URL safe // See RFC4648, section 5 for more info - public static string Encode(string arg) + public static string? Encode(string? arg) { if (arg == null) { @@ -68,7 +68,7 @@ public static byte[] DecodeToBytes(string arg) return Convert.FromBase64String(s); // Standard base64 decoder } - internal static string Encode(byte[] arg) + internal static string? Encode(byte[]? arg) { if (arg == null) { diff --git a/src/Microsoft.Identity.Web/ClaimsPrincipalExtensions.cs b/src/Microsoft.Identity.Web/ClaimsPrincipalExtensions.cs index 47e23a1ad..a9a925fa0 100644 --- a/src/Microsoft.Identity.Web/ClaimsPrincipalExtensions.cs +++ b/src/Microsoft.Identity.Web/ClaimsPrincipalExtensions.cs @@ -16,7 +16,7 @@ public static class ClaimsPrincipalExtensions /// /// Claims principal. /// A string corresponding to an account identifier as defined in . - public static string GetMsalAccountId(this ClaimsPrincipal claimsPrincipal) + public static string? GetMsalAccountId(this ClaimsPrincipal claimsPrincipal) { if (claimsPrincipal == null) { @@ -85,13 +85,13 @@ public static string GetLoginHint(this ClaimsPrincipal claimsPrincipal) /// /// Identity for which to compute the domain-hint. /// domain-hint for the identity, or null if it cannot be found. - public static string GetDomainHint(this ClaimsPrincipal claimsPrincipal) + public static string? GetDomainHint(this ClaimsPrincipal claimsPrincipal) { // Tenant for MSA accounts const string msaTenantId = "9188040d-6c67-4c5b-b112-36a304b66dad"; var tenantId = GetTenantId(claimsPrincipal); - string domainHint = string.IsNullOrWhiteSpace(tenantId) + string? domainHint = string.IsNullOrWhiteSpace(tenantId) ? null : tenantId.Equals(msaTenantId, StringComparison.OrdinalIgnoreCase) ? "consumers" : "organizations"; @@ -154,7 +154,7 @@ public static string GetHomeObjectId(this ClaimsPrincipal claimsPrincipal) { throw new ArgumentNullException(nameof(claimsPrincipal)); } - + return claimsPrincipal.FindFirstValue(ClaimConstants.UniqueObjectIdentifier); } diff --git a/src/Microsoft.Identity.Web/ClientInfo.cs b/src/Microsoft.Identity.Web/ClientInfo.cs index 17d4f52ba..23708ba8a 100644 --- a/src/Microsoft.Identity.Web/ClientInfo.cs +++ b/src/Microsoft.Identity.Web/ClientInfo.cs @@ -13,10 +13,10 @@ namespace Microsoft.Identity.Web internal class ClientInfo { [DataMember(Name = "uid", IsRequired = false)] - public string UniqueObjectIdentifier { get; set; } + public string? UniqueObjectIdentifier { get; set; } [DataMember(Name = "utid", IsRequired = false)] - public string UniqueTenantIdentifier { get; set; } + public string? UniqueTenantIdentifier { get; set; } public static ClientInfo CreateFromJson(string clientInfo) { @@ -25,19 +25,11 @@ public static ClientInfo CreateFromJson(string clientInfo) throw new ArgumentNullException(nameof(clientInfo), $"client info returned from the server is null"); } - return DeserializeFromJson(Base64UrlHelpers.DecodeToBytes(clientInfo)); - } - - internal static T DeserializeFromJson(byte[] jsonByteArray) - { - if (jsonByteArray == null || jsonByteArray.Length == 0) - { - return default; - } + var jsonByteArray = Base64UrlHelpers.DecodeToBytes(clientInfo); - using var stream = new MemoryStream(jsonByteArray); - using var reader = new StreamReader(stream, Encoding.UTF8); - return (T)JsonSerializer.Create().Deserialize(reader, typeof(T)); + using MemoryStream stream = new MemoryStream(jsonByteArray); + using StreamReader reader = new StreamReader(stream, Encoding.UTF8); + return (ClientInfo)JsonSerializer.Create().Deserialize(reader, typeof(ClientInfo)); } } } diff --git a/src/Microsoft.Identity.Web/HttpContextExtensions.cs b/src/Microsoft.Identity.Web/HttpContextExtensions.cs index 86758add1..d7b8a70b3 100644 --- a/src/Microsoft.Identity.Web/HttpContextExtensions.cs +++ b/src/Microsoft.Identity.Web/HttpContextExtensions.cs @@ -24,7 +24,7 @@ internal static void StoreTokenUsedToCallWebAPI(this HttpContext httpContext, Jw /// /// Http context associated with the current request. /// used to call the Web API. - internal static JwtSecurityToken GetTokenUsedToCallWebAPI(this HttpContext httpContext) + internal static JwtSecurityToken? GetTokenUsedToCallWebAPI(this HttpContext httpContext) { return httpContext.Items["JwtSecurityTokenUsedToCallWebAPI"] as JwtSecurityToken; } diff --git a/src/Microsoft.Identity.Web/ITokenAcquisition.cs b/src/Microsoft.Identity.Web/ITokenAcquisition.cs index 4ec300350..c150aa42d 100644 --- a/src/Microsoft.Identity.Web/ITokenAcquisition.cs +++ b/src/Microsoft.Identity.Web/ITokenAcquisition.cs @@ -22,7 +22,7 @@ public interface ITokenAcquisition /// Enables to override the tenant/account for the same identity. This is useful in the /// cases where a given account is guest in other tenants, and you want to acquire tokens for a specific tenant. /// An access token to call on behalf of the user, the downstream API characterized by its scopes. - Task GetAccessTokenForUserAsync(IEnumerable scopes, string tenantId = null); + Task GetAccessTokenForUserAsync(IEnumerable scopes, string? tenantId = null); /// /// Acquires a token from the authority configured in the app, for the confidential client itself (not on behalf of a user) diff --git a/src/Microsoft.Identity.Web/InstanceDiscovery/IssuerMetadata.cs b/src/Microsoft.Identity.Web/InstanceDiscovery/IssuerMetadata.cs index d899be766..b4a0ee2f6 100644 --- a/src/Microsoft.Identity.Web/InstanceDiscovery/IssuerMetadata.cs +++ b/src/Microsoft.Identity.Web/InstanceDiscovery/IssuerMetadata.cs @@ -15,18 +15,18 @@ internal class IssuerMetadata /// Tenant discovery endpoint. /// [JsonProperty(PropertyName = "tenant_discovery_endpoint")] - public string TenantDiscoveryEndpoint { get; set; } + public string? TenantDiscoveryEndpoint { get; set; } /// /// API Version. /// [JsonProperty(PropertyName = "api-version")] - public string ApiVersion { get; set; } + public string? ApiVersion { get; set; } /// /// List of metadata associated with the endpoint. /// [JsonProperty(PropertyName = "metadata")] - public List Metadata { get; set; } + public List? Metadata { get; set; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Identity.Web/InstanceDiscovery/Metadata.cs b/src/Microsoft.Identity.Web/InstanceDiscovery/Metadata.cs index e44ba6685..c49eeed24 100644 --- a/src/Microsoft.Identity.Web/InstanceDiscovery/Metadata.cs +++ b/src/Microsoft.Identity.Web/InstanceDiscovery/Metadata.cs @@ -15,19 +15,19 @@ internal class Metadata /// Preferred alias. /// [JsonProperty(PropertyName = "preferred_network")] - public string PreferredNetwork { get; set; } + public string? PreferredNetwork { get; set; } /// /// Preferred alias to cache tokens emitted by one of the aliases (to avoid /// SSO islands). /// [JsonProperty(PropertyName = "preferred_cache")] - public string PreferredCache { get; set; } + public string? PreferredCache { get; set; } /// /// Aliases of issuer URLs which are equivalent. /// [JsonProperty(PropertyName = "aliases")] - public List Aliases { get; set; } + public List? Aliases { get; set; } } -} \ No newline at end of file +} diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj index 4ceb8d22c..e988c1d41 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj @@ -1,6 +1,14 @@  - + + netcoreapp3.1 + true + ../../build/MSAL.snk + true + enable + + + 0.1.0-localbuild @@ -24,6 +32,7 @@ The changelog is available at https://github.com/AzureAD/microsoft-identity-web/blob/master/changelog.txt and the roadmap at https://github.com/AzureAD/microsoft-identity-web/wiki#roadmap Microsoft Identity Web .NET ASP.NET Core Web App Web API B2C + true true @@ -34,9 +43,6 @@ - - - True @@ -46,23 +52,6 @@ - - - - netcoreapp3.1 - true - ../../build/MSAL.snk - true - - - - - false - - - - C:\gh\microsoft-identity-web\src\Microsoft.Identity.Web\Microsoft.Identity.Web.xml - diff --git a/src/Microsoft.Identity.Web/Resource/AadIssuerValidator.cs b/src/Microsoft.Identity.Web/Resource/AadIssuerValidator.cs index 938309eda..ae7a37a19 100644 --- a/src/Microsoft.Identity.Web/Resource/AadIssuerValidator.cs +++ b/src/Microsoft.Identity.Web/Resource/AadIssuerValidator.cs @@ -49,10 +49,10 @@ public static AadIssuerValidator GetIssuerValidator(string aadAuthority) throw new ArgumentNullException(nameof(aadAuthority)); } - Uri.TryCreate(aadAuthority, UriKind.Absolute, out Uri authorityUri); + Uri.TryCreate(aadAuthority, UriKind.Absolute, out Uri? authorityUri); string authorityHost = authorityUri?.Authority ?? new Uri(FallbackAuthority).Authority; - if (s_issuerValidators.TryGetValue(authorityHost, out AadIssuerValidator aadIssuerValidator)) + if (s_issuerValidators.TryGetValue(authorityHost, out AadIssuerValidator? aadIssuerValidator)) { return aadIssuerValidator; } @@ -173,9 +173,9 @@ private static string GetTenantIdFromToken(SecurityToken securityToken) { if (securityToken is JwtSecurityToken jwtSecurityToken) { - if (jwtSecurityToken.Payload.TryGetValue(ClaimConstants.Tid, out object tenantId)) + if (jwtSecurityToken.Payload.TryGetValue(ClaimConstants.Tid, out object? tenantId)) { - return tenantId as string; + return (string)tenantId; } // Since B2C doesn't have "tid" as default, get it from issuer diff --git a/src/Microsoft.Identity.Web/Resource/OpenIdConnectMiddlewareDiagnostics.cs b/src/Microsoft.Identity.Web/Resource/OpenIdConnectMiddlewareDiagnostics.cs index e6a910e60..3491350fb 100644 --- a/src/Microsoft.Identity.Web/Resource/OpenIdConnectMiddlewareDiagnostics.cs +++ b/src/Microsoft.Identity.Web/Resource/OpenIdConnectMiddlewareDiagnostics.cs @@ -126,7 +126,7 @@ private void DisplayProtocolMessage(OpenIdConnectMessage message) { foreach (var property in message.GetType().GetProperties()) { - object value = property.GetValue(message); + object? value = property.GetValue(message); if (value != null) { _logger.LogDebug($" - {property.Name}={value}"); diff --git a/src/Microsoft.Identity.Web/Resource/RegisterValidAudience.cs b/src/Microsoft.Identity.Web/Resource/RegisterValidAudience.cs index 0c6c34667..13ba2e950 100644 --- a/src/Microsoft.Identity.Web/Resource/RegisterValidAudience.cs +++ b/src/Microsoft.Identity.Web/Resource/RegisterValidAudience.cs @@ -61,7 +61,12 @@ public void RegisterAudienceValidation( SecurityToken securityToken, TokenValidationParameters validationParameters) { - JwtSecurityToken token = securityToken as JwtSecurityToken; + JwtSecurityToken? token = securityToken as JwtSecurityToken; + if (token == null) + { + throw new SecurityTokenValidationException("Token is not JWT token."); + } + string validAudience; // Case of a default App ID URI (the developer did not provide explicit valid audience(s) diff --git a/src/Microsoft.Identity.Web/Resource/ScopesRequiredHttpContextExtensions.cs b/src/Microsoft.Identity.Web/Resource/ScopesRequiredHttpContextExtensions.cs index 43fb7b395..106bb2dde 100644 --- a/src/Microsoft.Identity.Web/Resource/ScopesRequiredHttpContextExtensions.cs +++ b/src/Microsoft.Identity.Web/Resource/ScopesRequiredHttpContextExtensions.cs @@ -33,7 +33,7 @@ public static void VerifyUserHasAnyAcceptedScope(this HttpContext context, param throw new ArgumentNullException(nameof(acceptedScopes)); } - Claim scopeClaim = context?.User?.FindFirst("http://schemas.microsoft.com/identity/claims/scope"); + Claim? scopeClaim = context?.User?.FindFirst("http://schemas.microsoft.com/identity/claims/scope"); if (scopeClaim == null || !scopeClaim.Value.Split(' ').Intersect(acceptedScopes).Any()) { diff --git a/src/Microsoft.Identity.Web/TokenAcquisition.cs b/src/Microsoft.Identity.Web/TokenAcquisition.cs index 98d5d6fad..8ec21be8a 100644 --- a/src/Microsoft.Identity.Web/TokenAcquisition.cs +++ b/src/Microsoft.Identity.Web/TokenAcquisition.cs @@ -35,7 +35,7 @@ internal class TokenAcquisition : ITokenAcquisition, ITokenAcquisitionInternal private IConfidentialClientApplication _application; private readonly IHttpContextAccessor _httpContextAccessor; private HttpContext CurrentHttpContext => _httpContextAccessor.HttpContext; - private IMsalHttpClientFactory _httpClientFactory; + private readonly IMsalHttpClientFactory _httpClientFactory; private readonly ILogger _logger; /// @@ -130,7 +130,7 @@ public async Task AddAccountToCacheFromAuthorizationCodeAsync( // If they are not yet in the HttpContext.User's claims, add them here. if (!context.HttpContext.User.Claims.Any()) { - (context.HttpContext.User.Identity as ClaimsIdentity).AddClaims(context.Principal.Claims); + (context.HttpContext.User.Identity as ClaimsIdentity)?.AddClaims(context.Principal.Claims); } _application = await GetOrBuildConfidentialClientApplicationAsync().ConfigureAwait(false); @@ -148,9 +148,7 @@ public async Task AddAccountToCacheFromAuthorizationCodeAsync( { _logger.LogInformation( ex, - string.Format( - CultureInfo.InvariantCulture, - "Exception occurred while adding an account to the cache from the auth code. ")); + "Exception occurred while adding an account to the cache from the auth code. "); throw; } } @@ -175,7 +173,7 @@ public async Task AddAccountToCacheFromAuthorizationCodeAsync( [Obsolete("This method has been deprecated, please use the GetAccessTokenForUserAsync() method instead.")] public async Task GetAccessTokenOnBehalfOfUserAsync( IEnumerable scopes, - string tenant = null) + string? tenant = null) { return await GetAccessTokenForUserAsync(scopes, tenant).ConfigureAwait(false); } @@ -189,7 +187,7 @@ public async Task GetAccessTokenOnBehalfOfUserAsync( /// instance of the current HttpContext. /// /// Scopes to request for the downstream API to call. - /// Enables overriding of the tenant/account for the same identity. This is useful in the + /// Enables overriding of the tenant/account for the same identity. This is useful in the /// cases where a given account is guest in other tenants, and you want to acquire tokens for a specific tenant, like where the user is a guest in. /// An access token to call the downstream API and populated with this downstream Api's scopes. /// Calling this method from a Web API supposes that you have previously called, @@ -199,7 +197,7 @@ public async Task GetAccessTokenOnBehalfOfUserAsync( /// OpenIdConnectOptions.Events.OnAuthorizationCodeReceived. public async Task GetAccessTokenForUserAsync( IEnumerable scopes, - string tenant = null) + string? tenantId = null) { if (scopes == null) { @@ -212,7 +210,7 @@ public async Task GetAccessTokenForUserAsync( try { - accessToken = await GetAccessTokenOnBehalfOfUserFromCacheAsync(_application, CurrentHttpContext.User, scopes, tenant) + accessToken = await GetAccessTokenOnBehalfOfUserFromCacheAsync(_application, CurrentHttpContext.User, scopes, tenantId) .ConfigureAwait(false); } catch (MsalUiRequiredException ex) @@ -401,12 +399,12 @@ private async Task GetAccessTokenOnBehalfOfUserFromCacheAsync( IConfidentialClientApplication application, ClaimsPrincipal claimsPrincipal, IEnumerable scopes, - string tenant) + string? tenant) { // Gets MsalAccountId for AAD and B2C scenarios string accountIdentifier = claimsPrincipal.GetMsalAccountId(); string loginHint = claimsPrincipal.GetLoginHint(); - IAccount account = null; + IAccount? account = null; if (accountIdentifier != null) { @@ -446,9 +444,9 @@ private async Task GetAccessTokenOnBehalfOfUserFromCacheAsync( /// private async Task GetAccessTokenOnBehalfOfUserFromCacheAsync( IConfidentialClientApplication application, - IAccount account, + IAccount? account, IEnumerable scopes, - string tenant) + string? tenant) { if (scopes == null) { diff --git a/src/Microsoft.Identity.Web/WebApiAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/WebApiAuthenticationBuilderExtensions.cs index ad131fdc0..f3d5d95db 100644 --- a/src/Microsoft.Identity.Web/WebApiAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/WebApiAuthenticationBuilderExtensions.cs @@ -39,7 +39,7 @@ public static AuthenticationBuilder AddProtectedWebApi( IConfiguration configuration, string configSectionName = "AzureAd", string jwtBearerScheme = JwtBearerDefaults.AuthenticationScheme, - X509Certificate2 tokenDecryptionCertificate = null, + X509Certificate2? tokenDecryptionCertificate = null, bool subscribeToJwtBearerMiddlewareDiagnosticsEvents = false) { return builder.AddProtectedWebApi( @@ -68,7 +68,7 @@ public static AuthenticationBuilder AddProtectedWebApi( this AuthenticationBuilder builder, Action configureJwtBearerOptions, Action configureMicrosoftIdentityOptions, - X509Certificate2 tokenDecryptionCertificate = null, + X509Certificate2? tokenDecryptionCertificate = null, string jwtBearerScheme = JwtBearerDefaults.AuthenticationScheme, bool subscribeToJwtBearerMiddlewareDiagnosticsEvents = false) { diff --git a/src/Microsoft.Identity.Web/WebApiServiceCollectionExtensions.cs b/src/Microsoft.Identity.Web/WebApiServiceCollectionExtensions.cs index 8a1289f8e..0fde92ea2 100644 --- a/src/Microsoft.Identity.Web/WebApiServiceCollectionExtensions.cs +++ b/src/Microsoft.Identity.Web/WebApiServiceCollectionExtensions.cs @@ -4,7 +4,6 @@ using System; using System.IdentityModel.Tokens.Jwt; using System.Security.Cryptography.X509Certificates; -using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.Extensions.Configuration; @@ -36,7 +35,7 @@ public static IServiceCollection AddProtectedWebApi( IConfiguration configuration, string configSectionName = "AzureAd", string jwtBearerScheme = JwtBearerDefaults.AuthenticationScheme, - X509Certificate2 tokenDecryptionCertificate = null, + X509Certificate2? tokenDecryptionCertificate = null, bool subscribeToJwtBearerMiddlewareDiagnosticsEvents = false) { AuthenticationBuilder builder = services.AddAuthentication(jwtBearerScheme); @@ -66,7 +65,7 @@ public static IServiceCollection AddProtectedWebApi( this IServiceCollection services, Action configureJwtBearerOptions, Action configureMicrosoftIdentityOptions, - X509Certificate2 tokenDecryptionCertificate = null, + X509Certificate2? tokenDecryptionCertificate = null, string jwtBearerScheme = JwtBearerDefaults.AuthenticationScheme, bool subscribeToJwtBearerMiddlewareDiagnosticsEvents = false) { diff --git a/src/Microsoft.Identity.Web/WebAppServiceCollectionExtensions.cs b/src/Microsoft.Identity.Web/WebAppServiceCollectionExtensions.cs index 65b5102e5..f4c0b4792 100644 --- a/src/Microsoft.Identity.Web/WebAppServiceCollectionExtensions.cs +++ b/src/Microsoft.Identity.Web/WebAppServiceCollectionExtensions.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Security.Claims; using Microsoft.AspNetCore.Authentication; @@ -158,7 +159,7 @@ public static IServiceCollection AddWebAppCallsProtectedWebApi( /// The service collection for chaining. public static IServiceCollection AddWebAppCallsProtectedWebApi( this IServiceCollection services, - IEnumerable initialScopes, + IEnumerable? initialScopes, Action configureMicrosoftIdentityOptions, Action configureConfidentialClientApplicationOptions, string openIdConnectScheme = OpenIdConnectDefaults.AuthenticationScheme) @@ -198,7 +199,7 @@ public static IServiceCollection AddWebAppCallsProtectedWebApi( var codeReceivedHandler = options.Events.OnAuthorizationCodeReceived; options.Events.OnAuthorizationCodeReceived = async context => { - var tokenAcquisition = context.HttpContext.RequestServices.GetRequiredService() as ITokenAcquisitionInternal; + var tokenAcquisition = (ITokenAcquisitionInternal)context.HttpContext.RequestServices.GetRequiredService(); await tokenAcquisition.AddAccountToCacheFromAuthorizationCodeAsync(context, options.Scope).ConfigureAwait(false); await codeReceivedHandler(context).ConfigureAwait(false); }; @@ -232,7 +233,7 @@ public static IServiceCollection AddWebAppCallsProtectedWebApi( options.Events.OnRedirectToIdentityProviderForSignOut = async context => { // Remove the account from MSAL.NET token cache - var tokenAcquisition = context.HttpContext.RequestServices.GetRequiredService() as ITokenAcquisitionInternal; + var tokenAcquisition = (ITokenAcquisitionInternal)context.HttpContext.RequestServices.GetRequiredService(); await tokenAcquisition.RemoveAccountAsync(context).ConfigureAwait(false); await signOutHandler(context).ConfigureAwait(false); }; diff --git a/tests/Microsoft.Identity.Web.Test/ClientInfoTests.cs b/tests/Microsoft.Identity.Web.Test/ClientInfoTests.cs index 01347204c..e5fd8139e 100644 --- a/tests/Microsoft.Identity.Web.Test/ClientInfoTests.cs +++ b/tests/Microsoft.Identity.Web.Test/ClientInfoTests.cs @@ -54,13 +54,13 @@ public void CreateFromJson_InvalidString_ThrowsException() [Fact] public void DeserializeFromJson_ValidByteArray_ReturnsClientInfo() { - var clientInfoResult = ClientInfo.DeserializeFromJson(Encoding.UTF8.GetBytes(_decodedJson)); + var clientInfoResult = ClientInfo.CreateFromJson(_decodedJson); Assert.NotNull(clientInfoResult); Assert.Equal(Uid, clientInfoResult.UniqueObjectIdentifier); Assert.Equal(Utid, clientInfoResult.UniqueTenantIdentifier); - clientInfoResult = ClientInfo.DeserializeFromJson(Encoding.UTF8.GetBytes(_decodedEmptyJson)); + clientInfoResult = ClientInfo.CreateFromJson(_decodedEmptyJson); Assert.NotNull(clientInfoResult); Assert.Null(clientInfoResult.UniqueObjectIdentifier); Assert.Null(clientInfoResult.UniqueTenantIdentifier); @@ -69,11 +69,11 @@ public void DeserializeFromJson_ValidByteArray_ReturnsClientInfo() [Fact] public void DeserializeFromJson_NullOrEmptyJsonByteArray_ReturnsNull() { - var actualClientInfo = ClientInfo.DeserializeFromJson(Array.Empty()); + var actualClientInfo = ClientInfo.CreateFromJson(""); Assert.Null(actualClientInfo); - actualClientInfo = ClientInfo.DeserializeFromJson(null); + actualClientInfo = ClientInfo.CreateFromJson(null); Assert.Null(actualClientInfo); } @@ -81,7 +81,7 @@ public void DeserializeFromJson_NullOrEmptyJsonByteArray_ReturnsNull() [Fact] public void DeserializeFromJson_InvalidJsonByteArray_ReturnsNull() { - Assert.Throws(() => ClientInfo.DeserializeFromJson(Encoding.UTF8.GetBytes(_invalidJson))); + Assert.Throws(() => ClientInfo.CreateFromJson(_invalidJson)); } } }