public void ValidateJsonWebToken_ReturnsIssuer(string tidClaimType, string issuer) { var context = new CompareContext(); var validator = new AadIssuerValidator(_httpClient, issuer); var tidClaim = new Claim(tidClaimType, ValidatorConstants.TenantIdAsGuid); var issClaim = new Claim(ValidatorConstants.ClaimNameIss, issuer); List <Claim> claims = new List <Claim>(); claims.Add(tidClaim); claims.Add(issClaim); var jsonWebToken = new JsonWebToken(Default.Jwt(Default.SecurityTokenDescriptor(Default.SymmetricSigningCredentials, claims))); var tokenValidationParams = new TokenValidationParameters() { ConfigurationManager = new MockConfigurationManager <OpenIdConnectConfiguration>(new OpenIdConnectConfiguration() { Issuer = issuer }) }; var actualIssuer = validator.Validate(issuer, jsonWebToken, tokenValidationParams); IdentityComparer.AreEqual(issuer, actualIssuer, context); TestUtilities.AssertFailIfErrors(context); }
public static IServiceCollection AddPop( this IServiceCollection services, IConfiguration configuration, string configSectionName = "AzureAd") { services.AddAuthentication(SignedHttpRequestDefaults.AuthenticationScheme) .AddSignedHttpRequest(options => configuration.Bind(configSectionName, options)); services.Configure <SignedHttpRequestOptions>(options => configuration.Bind(configSectionName, options)); services.AddHttpContextAccessor(); // Change the authentication configuration to accommodate the Microsoft identity platform endpoint (v2.0). services.Configure <SignedHttpRequestOptions>(SignedHttpRequestDefaults.AuthenticationScheme, options => { options.Authority = options.Instance + options.Domain; // This is an Microsoft identity platform Web API options.Authority += "/v2.0"; // The valid audiences are both the Client ID (options.Audience) and api://{ClientID} options.AccessTokenValidationParameters.ValidAudiences = new string[] { options.ClientId, $"api://{options.ClientId}" }; // Instead of using the default validation (validating against a single tenant, as we do in line of business apps), // we inject our own multi-tenant validation logic (which even accepts both v1.0 and v2.0 tokens) options.AccessTokenValidationParameters.IssuerValidator = AadIssuerValidator.GetIssuerValidator(options.Authority).Validate; }); return(services); }
public void Validate_NotMatchedToMultipleIssuers_ThrowsException() { var validator = new AadIssuerValidator(TestConstants.s_aliases); var issClaim = new Claim(TestConstants.ClaimNameIss, TestConstants.AadIssuer); var tidClaim = new Claim(TestConstants.ClaimNameTid, TestConstants.TenantIdAsGuid); var jwtSecurityToken = new JwtSecurityToken(issuer: TestConstants.AadIssuer, claims: new[] { issClaim, tidClaim }); var expectedErrorMessage = string.Format( CultureInfo.InvariantCulture, IDWebErrorMessage.IssuerDoesNotMatchValidIssuers, TestConstants.AadIssuer); var exception = Assert.Throws <SecurityTokenInvalidIssuerException>(() => validator.Validate( TestConstants.AadIssuer, jwtSecurityToken, new TokenValidationParameters() { ValidIssuers = new[] { "https://host1/{tenantid}/v2.0", "https://host2/{tenantid}/v2.0", }, })); Assert.Equal(expectedErrorMessage, exception.Message); }
/// <summary> /// Protects the Web API with Microsoft identity platform (formerly Azure AD v2.0) /// This method expects the configuration file will have a section named "AzureAd" with the necessary settings to initialize authentication options. /// </summary> /// <param name="services">Service collection to which to add this authentication scheme</param> /// <param name="configuration">The Configuration object</param> /// <param name="subscribeToJwtBearerMiddlewareDiagnosticsEvents"> /// Set to true if you want to debug, or just understand the JwtBearer events. /// </param> /// <returns></returns> public static IServiceCollection AddProtectedWebApi( this IServiceCollection services, IConfiguration configuration, X509Certificate2 tokenDecryptionCertificate = null, string configSectionName = "AzureAd", bool subscribeToJwtBearerMiddlewareDiagnosticsEvents = false) { services.AddAuthentication(AzureADDefaults.JwtBearerAuthenticationScheme) .AddAzureADBearer(options => configuration.Bind(configSectionName, options)); services.Configure <AzureADOptions>(options => configuration.Bind(configSectionName, options)); services.AddHttpContextAccessor(); // Change the authentication configuration to accommodate the Microsoft identity platform endpoint (v2.0). services.Configure <JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationScheme, options => { // This is an Microsoft identity platform Web API options.Authority += "/v2.0"; // The valid audiences are both the Client ID (options.Audience) and api://{ClientID} options.TokenValidationParameters.ValidAudiences = new string[] { options.Audience, $"api://{options.Audience}" }; // Instead of using the default validation (validating against a single tenant, as we do in line of business apps), // we inject our own multi-tenant validation logic (which even accepts both v1.0 and v2.0 tokens) options.TokenValidationParameters.IssuerValidator = AadIssuerValidator.GetIssuerValidator(options.Authority).Validate; // If you provide a token decryption certificate, it will be used to decrypt the token if (tokenDecryptionCertificate != null) { options.TokenValidationParameters.TokenDecryptionKey = new X509SecurityKey(tokenDecryptionCertificate); } // When an access token for our own Web API is validated, we add it to MSAL.NET's cache so that it can // be used from the controllers. options.Events = new JwtBearerEvents(); options.Events.OnTokenValidated = async context => { // This check is required to ensure that the Web API only accepts tokens from tenants where it has been consented and provisioned. if (!context.Principal.Claims.Any(x => x.Type == ClaimConstants.Scope) && !context.Principal.Claims.Any(y => y.Type == ClaimConstants.Scp) && !context.Principal.Claims.Any(y => y.Type == ClaimConstants.Roles)) { throw new UnauthorizedAccessException("Neither scope or roles claim was found in the bearer token."); } await Task.FromResult(0); }; if (subscribeToJwtBearerMiddlewareDiagnosticsEvents) { options.Events = JwtBearerMiddlewareDiagnostics.Subscribe(options.Events); } }); return(services); }
public void Validate_IssuerMatchedInValidV1Issuer_ReturnsIssuer(string tidClaimType, string tenantId, string issuer) { var context = new CompareContext(); var validator = new AadIssuerValidator(_httpClient, issuer); var tidClaim = new Claim(tidClaimType, tenantId); var issClaim = new Claim(ValidatorConstants.ClaimNameIss, issuer); var jwtSecurityToken = new JwtSecurityToken(issuer: issuer, claims: new[] { issClaim, tidClaim }); validator.AadIssuerV1 = issuer; var actualIssuer = validator.Validate(issuer, jwtSecurityToken, new TokenValidationParameters() { ValidIssuer = issuer }); IdentityComparer.AreEqual(issuer, actualIssuer, context); var actualIssuers = validator.Validate(issuer, jwtSecurityToken, new TokenValidationParameters() { ValidIssuers = new[] { issuer } }); IdentityComparer.AreEqual(issuer, actualIssuers, context); TestUtilities.AssertFailIfErrors(context); }
/// <summary> /// Protects the Web API with Microsoft Identity Platform v2.0 (AAD v2.0) /// This supposes that the configuration files have a section named "AzureAD" /// </summary> /// <param name="services">Service collection to which to add authentication</param> /// <param name="configuration">Configuration</param> /// <returns></returns> public static IServiceCollection AddProtectWebApiWithMicrosoftIdentityPlatformV2(this IServiceCollection services, IConfiguration configuration) { services.AddAuthentication(AzureADDefaults.JwtBearerAuthenticationScheme) .AddAzureADBearer(options => configuration.Bind("AzureAd", options)); services.AddSession(); // Added services.Configure <JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationScheme, options => { // This is an Azure AD v2.0 Web API options.Authority += "/v2.0"; // The valid audiences are both the Client ID (options.Audience) and api://{ClientID} options.TokenValidationParameters.ValidAudiences = new string[] { options.Audience, $"api://{options.Audience}" }; // Instead of using the default validation (validating against a single tenant, as we do in line of business apps), // we inject our own multitenant validation logic (which even accepts both V1 and V2 tokens) options.TokenValidationParameters.IssuerValidator = AadIssuerValidator.ForAadInstance(options.Authority).ValidateAadIssuer; // When an access token for our own Web API is validated, we add it to MSAL.NET's cache so that it can // be used from the controllers. options.Events = new JwtBearerEvents(); // If you want to debug, or just understand the JwtBearer events, uncomment the following line of code // options.Events = JwtBearerMiddlewareDiagnostics.Subscribe(options.Events); }); return(services); }
public void GetIssuerValidator_InvalidAuthority_ReturnsValidatorBasedOnFallbackAuthority() { var invalidAuthority = "login.microsoft.com"; var validator = AadIssuerValidator.GetIssuerValidator(invalidAuthority); Assert.NotNull(validator); }
public void GetIssuerValidator_B2cAuthorityNotInAliases_ReturnsValidator() { var authorityNotInAliases = TestConstants.B2CAuthorityWithV2; var validator = AadIssuerValidator.GetIssuerValidator(authorityNotInAliases); Assert.NotNull(validator); }
public void GetIssuerValidator_AuthorityInAliases_ReturnsValidator() { var authorityInAliases = TestConstants.AuthorityCommonTenantWithV2; var validator = AadIssuerValidator.GetIssuerValidator(authorityInAliases); Assert.NotNull(validator); }
private void SetupAdAuthenticationV2(IServiceCollection services) { services.AddAuthentication(AzureADDefaults.JwtBearerAuthenticationScheme) .AddAzureADBearer(options => { this.Configuration.Bind("AzureAd", options); Console.WriteLine($"the AddAzureADBearer options have been configured for ClientId = {options.ClientId}"); }); services.AddSession(); services.AddTokenAcquisition(); // Added services.Configure <JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationScheme, options => { var scopes = new[] { PathwaysConstants.Graph.ScopeUserRead }; this.Configuration.Bind("AzureAd", options); // This is an Azure AD v2.0 Web API options.Authority += "/v2.0"; // The valid audiences are both the Client ID (options.Audience) and api://{ClientID} options.TokenValidationParameters.ValidAudiences = new[] { options.Audience, $"api://{options.Audience}" }; // Instead of using the default validation (validating against a single tenant, as we do in line of business apps), // we inject our own multitenant validation logic (which even accepts both V1 and V2 tokens) options.TokenValidationParameters.IssuerValidator = AadIssuerValidator.ForAadInstance(options.Authority).ValidateAadIssuer; // When an access token for our own Web API is validated, we add it to MSAL.NET's cache so that it can // be used from the controllers. // options.Events = new JwtBearerEvents(); // If you want to debug, or just understand the JwtBearer events, uncomment the following line of code // Events e = new Events(); options.Events = JwtBearerMiddlewareDiagnostics.Subscribe(options.Events); options.Events.OnTokenValidated = async context => { if (scopes != null && scopes.Any()) { var tokenAcquisition = context.HttpContext.RequestServices.GetRequiredService <ITokenAcquisition>(); context.Success(); tokenAcquisition.AddAccountToCacheFromJwt(context, scopes); } else { context.Success(); // Todo : rather use options.SaveToken? (context.Principal.Identity as ClaimsIdentity).AddClaim(new Claim("jwt", (context.SecurityToken as JwtSecurityToken).RawData)); } // Adds the token to the cache, and also handles the incremental consent and claim challenges await Task.FromResult(0); }; }); services.AddMsal(new[] { PathwaysConstants.Graph.ScopeUserRead }); services.AddInMemoryTokenCaches(); }
public void GetIssuerValidator_CachedAuthority_ReturnsCachedValidator() { var authorityNotInAliases = TestConstants.AuthorityWithTenantSpecifiedWithV2; var validator1 = AadIssuerValidator.GetIssuerValidator(authorityNotInAliases); var validator2 = AadIssuerValidator.GetIssuerValidator(authorityNotInAliases); Assert.Same(validator1, validator2); }
/// <summary> /// Protects the Web API with Microsoft identity platform /// This expects the configuration files will have a section named "AzureAD" /// </summary> /// <param name="services">Service collection to which to add authentication</param> /// <param name="configuration">Configuration</param> /// <param name="tokenDecryptionCertificate"></param> /// <returns></returns> public static IServiceCollection AddProtectWebApiWithMicrosoftIdentityPlatformV2(this IServiceCollection services, IConfiguration configuration, X509Certificate2 tokenDecryptionCertificate = null) { services.AddAuthentication(AzureADDefaults.JwtBearerAuthenticationScheme) .AddAzureADBearer(options => configuration.Bind("AzureAd", options)); // Add session if you are planning to use session based token cache , .AddSessionTokenCaches() //services.AddSession(); // Change the authentication configuration to accommodate the Microsoft identity platform endpoint. services.Configure <JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationScheme, options => { // Reinitialize the options as this has changed to JwtBearerOptions to pick configuration values for attributes unique to JwtBearerOptions configuration.Bind("AzureAd", options); // This is an Microsoft identity platform Web API options.Authority += "/v2.0"; // The valid audiences are both the Client ID (options.Audience) and api://{ClientID} options.TokenValidationParameters.ValidAudiences = new[] { options.Audience, $"api://{options.Audience}" }; // Instead of using the default validation (validating against a single tenant, as we do in line of business apps), // we inject our own multitenant validation logic (which even accepts both V1 and V2 tokens) options.TokenValidationParameters.IssuerValidator = AadIssuerValidator.GetIssuerValidator(options.Authority).Validate; // If you provide a token decryption certificate, it will be used to decrypt the token if (tokenDecryptionCertificate != null) { options.TokenValidationParameters.TokenDecryptionKey = new X509SecurityKey(tokenDecryptionCertificate); } // When an access token for our own Web API is validated, we add it to MSAL.NET's cache so that it can // be used from the controllers. options.Events = new JwtBearerEvents { OnTokenValidated = async context => { // This check is required to ensure that the Web API only accepts tokens from tenants where it has been consented and provisioned. if (context.Principal.Claims.All(x => x.Type != ClaimConstants.Scope) && context.Principal.Claims.All(y => y.Type != ClaimConstants.Roles)) { throw new UnauthorizedAccessException( "Neither scope or roles claim was found in the bearer token."); } await Task.FromResult(0); } }; // If you want to debug, or just understand the JwtBearer events, uncomment the following line of code // options.Events = JwtBearerMiddlewareDiagnostics.Subscribe(options.Events); }); return(services); }
public void NullArg() { // Arrange AadIssuerValidator validator = new AadIssuerValidator(s_aliases); var jwtSecurityToken = new JwtSecurityToken(); var validationParams = new TokenValidationParameters(); // Act and Assert Assert.Throws <ArgumentNullException>(() => validator.Validate(null, jwtSecurityToken, validationParams)); Assert.Throws <ArgumentNullException>(() => validator.Validate("", jwtSecurityToken, validationParams)); Assert.Throws <ArgumentNullException>(() => validator.Validate(Iss, null, validationParams)); Assert.Throws <ArgumentNullException>(() => validator.Validate(Iss, jwtSecurityToken, null)); }
public void Validate_TenantIdInIssuerNotInToken_ReturnsIssuer() { var validator = new AadIssuerValidator(TestConstants.s_aliases); var issClaim = new Claim(TestConstants.ClaimNameIss, TestConstants.AadIssuer); var jwtSecurityToken = new JwtSecurityToken(issuer: TestConstants.AadIssuer, claims: new[] { issClaim }); var actualIssuer = validator.Validate(TestConstants.AadIssuer, jwtSecurityToken, new TokenValidationParameters() { ValidIssuer = TestConstants.AadIssuer }); Assert.Equal(TestConstants.AadIssuer, actualIssuer); }
public static IServiceCollection AddProofOfPossession( this IServiceCollection services, IConfiguration configuration, string configSectionName = "AzureAd") { services.AddAuthentication(SignedHttpRequestDefaults.AuthenticationScheme) .AddSignedHttpRequest(options => configuration.Bind(configSectionName, options)); services.Configure <SignedHttpRequestOptions>(options => configuration.Bind(configSectionName, options)); services.AddHttpContextAccessor(); // Change the authentication configuration to accommodate the Microsoft identity platform endpoint (v2.0). services.Configure <SignedHttpRequestOptions>(SignedHttpRequestDefaults.AuthenticationScheme, options => { options.Authority = options.Instance + options.Domain; // This is an Microsoft identity platform Web API options.Authority += "/v2.0"; // The valid audiences are both the Client ID (options.Audience) and api://{ClientID} options.AccessTokenValidationParameters.ValidAudiences = new string[] { options.ClientId, $"api://{options.ClientId}" }; // Instead of using the default validation (validating against a single tenant, as we do in line of business apps), // we inject our own multi-tenant validation logic (which even accepts both v1.0 and v2.0 tokens) options.AccessTokenValidationParameters.IssuerValidator = AadIssuerValidator.GetIssuerValidator(options.Authority).Validate; options.Events ??= new SignedHttpRequest.Events.SignedHttpRequestEvents(); var onAuthenticationFailed = options.Events.OnAuthenticationFailed; options.Events.OnAuthenticationFailed = async context => { await onAuthenticationFailed(context).ConfigureAwait(false); }; var onMessageReceivedHandler = options.Events.OnMessageReceived; options.Events.OnMessageReceived = async context => { await onMessageReceivedHandler(context).ConfigureAwait(false); }; var tokenvalidationHandler = options.Events.OnTokenValidated; options.Events.OnTokenValidated = async context => { context.HttpContext.Items["JwtSecurityTokenUsedToCallWebAPI"] = context.SecurityToken; await tokenvalidationHandler(context).ConfigureAwait(false); }; }); return(services); }
public void Validate_NullOrEmptyParameters_ThrowsException() { var validator = new AadIssuerValidator(TestConstants.s_aliases); var jwtSecurityToken = new JwtSecurityToken(); var validationParams = new TokenValidationParameters(); var exception = Assert.Throws <ArgumentNullException>("actualIssuer", () => validator.Validate(null, jwtSecurityToken, validationParams)); exception = Assert.Throws <ArgumentNullException>("actualIssuer", () => validator.Validate(string.Empty, jwtSecurityToken, validationParams)); exception = Assert.Throws <ArgumentNullException>("securityToken", () => validator.Validate(TestConstants.AadIssuer, null, validationParams)); exception = Assert.Throws <ArgumentNullException>("validationParameters", () => validator.Validate(TestConstants.AadIssuer, jwtSecurityToken, null)); }
public void Validate_IssuerMatchedInValidIssuers_ReturnsIssuer() { var validator = new AadIssuerValidator(TestConstants.s_aliases); var tidClaim = new Claim(TestConstants.ClaimNameTid, TestConstants.TenantIdAsGuid); var issClaim = new Claim(TestConstants.ClaimNameIss, TestConstants.AadIssuer); var jwtSecurityToken = new JwtSecurityToken(issuer: TestConstants.AadIssuer, claims: new[] { issClaim, tidClaim }); var actualIssuer = validator.Validate(TestConstants.AadIssuer, jwtSecurityToken, new TokenValidationParameters() { ValidIssuers = new[] { TestConstants.AadIssuer } }); Assert.Equal(TestConstants.AadIssuer, actualIssuer); }
public void TokenValidationParameters_ValidIssuer() { // Arrange AadIssuerValidator validator = new AadIssuerValidator(s_aliases); Claim issClaim = new Claim("tid", Tid); Claim tidClaim = new Claim("iss", Iss); JwtSecurityToken jwtSecurityToken = new JwtSecurityToken(issuer: Iss, claims: new[] { issClaim, tidClaim }); // Act & Assert validator.Validate(Iss, jwtSecurityToken, new TokenValidationParameters() { ValidIssuer = "https://login.microsoftonline.com/{tenantid}/v2.0" }); }
public void Validate_TenantIdInIssuerNotInToken_ReturnsIssuer() { var context = new CompareContext(); var validator = new AadIssuerValidator(_httpClient, ValidatorConstants.AadIssuer); var issClaim = new Claim(ValidatorConstants.ClaimNameIss, ValidatorConstants.AadIssuer); var jwtSecurityToken = new JwtSecurityToken(issuer: ValidatorConstants.AadIssuer, claims: new[] { issClaim }); var actualIssuer = validator.Validate(ValidatorConstants.AadIssuer, jwtSecurityToken, new TokenValidationParameters() { ValidIssuer = ValidatorConstants.AadIssuer }); IdentityComparer.AreEqual(ValidatorConstants.AadIssuer, actualIssuer, context); TestUtilities.AssertFailIfErrors(context); }
public void PassingValidationWithAlias() { // Arrange AadIssuerValidator validator = new AadIssuerValidator(s_aliases); Claim issClaim = new Claim("tid", Tid); Claim tidClaim = new Claim("iss", Iss2);// sts.windows.net JwtSecurityToken jwtSecurityToken = new JwtSecurityToken(issuer: Iss2, claims: new[] { issClaim, tidClaim }); // Act & Assert validator.Validate(Iss2, jwtSecurityToken, new TokenValidationParameters() { ValidIssuers = new[] { "https://login.microsoftonline.com/{tenantid}/v2.0" } }); }
public void Validate_NotMatchedTenantIds_ThrowsException() { var validator = new AadIssuerValidator(TestConstants.s_aliases); var issClaim = new Claim(TestConstants.ClaimNameIss, TestConstants.AadIssuer); var tidClaim = new Claim(TestConstants.ClaimNameTid, TestConstants.B2CTenantAsGuid); var jwtSecurityToken = new JwtSecurityToken(issuer: TestConstants.AadIssuer, claims: new[] { issClaim, tidClaim }); var expectedErrorMessage = $"Issuer: '{TestConstants.AadIssuer}', does not match any of the valid issuers provided for this application."; var exception = Assert.Throws <SecurityTokenInvalidIssuerException>(() => validator.Validate(TestConstants.AadIssuer, jwtSecurityToken, new TokenValidationParameters() { ValidIssuer = TestConstants.AadIssuer })); Assert.Equal(expectedErrorMessage, exception.Message); }
public void Validate_FromCustomB2CAuthority_ValidateSuccessfully() { Claim issClaim = new Claim(TestConstants.ClaimNameIss, TestConstants.B2CCustomDomainIssuer); Claim tfpClaim = new Claim(TestConstants.ClaimNameTfp, TestConstants.B2CSignUpSignInUserFlow); JwtSecurityToken jwtSecurityToken = new JwtSecurityToken(issuer: TestConstants.B2CCustomDomainIssuer, claims: new[] { issClaim, tfpClaim }); AadIssuerValidator validator = AadIssuerValidator.GetIssuerValidator(TestConstants.B2CCustomDomainAuthorityWithV2); validator.Validate( TestConstants.B2CCustomDomainIssuer, jwtSecurityToken, new TokenValidationParameters() { ValidIssuers = new[] { TestConstants.B2CCustomDomainIssuer }, }); }
public void Validate_InvalidIssuerToValidate_ThrowsException() { string invalidIssuerToValidate = $"https://badissuer/{TestConstants.TenantIdAsGuid}/v2.0"; AadIssuerValidator validator = new AadIssuerValidator(TestConstants.s_aliases); Claim issClaim = new Claim(TestConstants.ClaimNameIss, TestConstants.AadIssuer); Claim tidClaim = new Claim(TestConstants.ClaimNameTid, TestConstants.TenantIdAsGuid); JwtSecurityToken jwtSecurityToken = new JwtSecurityToken(issuer: TestConstants.AadIssuer, claims: new[] { issClaim, tidClaim }); var expectedErrorMessage = $"Issuer: '{invalidIssuerToValidate}', does not match any of the valid issuers provided for this application."; var exception = Assert.Throws <SecurityTokenInvalidIssuerException>(() => validator.Validate(invalidIssuerToValidate, jwtSecurityToken, new TokenValidationParameters() { ValidIssuers = new[] { TestConstants.AadIssuer } })); Assert.Equal(expectedErrorMessage, exception.Message); }
public void ValidationSucceeds_NoTidClaimInJwt_TidCreatedFromIssuerInstead() { // Arrange AadIssuerValidator validator = new AadIssuerValidator(s_aliases); Claim issClaim = new Claim("iss", Iss); JwtSecurityToken noTidJwt = new JwtSecurityToken(issuer: Iss, claims: new[] { issClaim }); // Act & Assert validator.Validate( Iss, noTidJwt, new TokenValidationParameters() { ValidIssuers = new[] { "https://login.microsoftonline.com/{tenantid}/v2.0" } }); }
public void Validate_FromB2CAuthority_InvalidIssuer_Fails() { Claim issClaim = new Claim(TestConstants.ClaimNameIss, TestConstants.B2CIssuer2); Claim tfpClaim = new Claim(TestConstants.ClaimNameTfp, TestConstants.B2CSignUpSignInUserFlow); JwtSecurityToken jwtSecurityToken = new JwtSecurityToken(issuer: TestConstants.B2CIssuer2, claims: new[] { issClaim, tfpClaim }); AadIssuerValidator validator = AadIssuerValidator.GetIssuerValidator(TestConstants.B2CAuthorityWithV2); Assert.Throws <SecurityTokenInvalidIssuerException>(() => validator.Validate( TestConstants.B2CIssuer2, jwtSecurityToken, new TokenValidationParameters() { ValidIssuers = new[] { TestConstants.B2CIssuer }, })); }
public void Validate_FromB2CAuthority_WithTidClaim_ValidateSuccessfully() { Claim issClaim = new Claim(TestConstants.ClaimNameIss, TestConstants.B2CIssuer); Claim tfpClaim = new Claim(TestConstants.ClaimNameTfp, TestConstants.B2CSuSiUserFlow); Claim tidClaim = new Claim(TestConstants.ClaimNameTid, TestConstants.B2CTenantAsGuid); JwtSecurityToken jwtSecurityToken = new JwtSecurityToken(issuer: TestConstants.B2CIssuer, claims: new[] { issClaim, tfpClaim, tidClaim }); AadIssuerValidator validator = AadIssuerValidator.GetIssuerValidator(TestConstants.B2CAuthorityWithV2); validator.Validate( TestConstants.B2CIssuer, jwtSecurityToken, new TokenValidationParameters() { ValidIssuers = new[] { TestConstants.B2CIssuer } }); }
public void Validate_NullOrEmptyParameters_ThrowsException() { var context = new CompareContext(); var validator = new AadIssuerValidator(_httpClient, ValidatorConstants.AadIssuer); var jwtSecurityToken = new JwtSecurityToken(); var validationParams = new TokenValidationParameters(); Assert.Throws <ArgumentNullException>(ValidatorConstants.Issuer, () => validator.Validate(null, jwtSecurityToken, validationParams)); var exception = Assert.Throws <SecurityTokenInvalidIssuerException>(() => validator.Validate(string.Empty, jwtSecurityToken, validationParams)); IdentityComparer.AreEqual(LogMessages.IDX40003, exception.Message); Assert.Throws <ArgumentNullException>(ValidatorConstants.SecurityToken, () => validator.Validate(ValidatorConstants.AadIssuer, null, validationParams)); Assert.Throws <ArgumentNullException>(ValidatorConstants.ValidationParameters, () => validator.Validate(ValidatorConstants.AadIssuer, jwtSecurityToken, null)); TestUtilities.AssertFailIfErrors(context); }
public void ValidationFails_NoTidClaimInJwt() { // Arrange AadIssuerValidator validator = new AadIssuerValidator(s_aliases); Claim issClaim = new Claim("iss", Iss); JwtSecurityToken noTidJwt = new JwtSecurityToken(issuer: Iss, claims: new[] { issClaim }); // Act & Assert Assert.Throws <SecurityTokenInvalidIssuerException>(() => validator.Validate( Iss, noTidJwt, new TokenValidationParameters() { ValidIssuers = new[] { "https://login.microsoftonline.com/{tenantid}/v2.0" } })); }
public void Validate_FromB2CAuthority_InvalidIssuerTid_Fails() { string issuerWithInvalidTid = TestConstants.B2CInstance + "/" + TestConstants.TenantIdAsGuid + "/v2.0"; Claim issClaim = new Claim(TestConstants.ClaimNameIss, issuerWithInvalidTid); Claim tfpClaim = new Claim(TestConstants.ClaimNameTfp, TestConstants.B2CSignUpSignInUserFlow); JwtSecurityToken jwtSecurityToken = new JwtSecurityToken(issuer: issuerWithInvalidTid, claims: new[] { issClaim, tfpClaim }); AadIssuerValidator validator = AadIssuerValidator.GetIssuerValidator(TestConstants.B2CAuthorityWithV2); Assert.Throws <SecurityTokenInvalidIssuerException>(() => validator.Validate( issuerWithInvalidTid, jwtSecurityToken, new TokenValidationParameters() { ValidIssuers = new[] { TestConstants.B2CIssuer }, })); }
public void Validate_NullOrEmptyTenantId_ThrowsException() { var validator = new AadIssuerValidator(TestConstants.s_aliases); var jwtSecurityToken = new JwtSecurityToken(); var jsonWebToken = new JsonWebToken($"{{}}", $"{{}}"); var securityToken = Substitute.For <SecurityToken>(); var validationParameters = new TokenValidationParameters(); var exception = Assert.Throws <SecurityTokenInvalidIssuerException>(() => validator.Validate(TestConstants.AadIssuer, jwtSecurityToken, validationParameters)); Assert.Equal(IDWebErrorMessage.TenantIdClaimNotPresentInToken, exception.Message); exception = Assert.Throws <SecurityTokenInvalidIssuerException>(() => validator.Validate(TestConstants.AadIssuer, jsonWebToken, validationParameters)); Assert.Equal(IDWebErrorMessage.TenantIdClaimNotPresentInToken, exception.Message); exception = Assert.Throws <SecurityTokenInvalidIssuerException>(() => validator.Validate(TestConstants.AadIssuer, securityToken, validationParameters)); Assert.Equal(IDWebErrorMessage.TenantIdClaimNotPresentInToken, exception.Message); }