Пример #1
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        /// <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);
        }
Пример #5
0
        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);
        }
Пример #6
0
        /// <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);
        }
Пример #12
0
        /// <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);
        }
Пример #13
0
        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);
        }
Пример #18
0
        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"
            });
        }
Пример #19
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);
        }
Пример #20
0
        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);
        }
Пример #24
0
        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 }
            });
        }
Пример #27
0
        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 },
            }));
        }
Пример #30
0
        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);
        }