Пример #1
0
        public void GetAuthorizationCodeRequestUrl_InvalidProviderSetup(string clientId, string clientSecret, string configUrl, string claim, bool enabled)
        {
            var mockRepo         = new MockRepository(MockBehavior.Loose);
            var configManager    = mockRepo.Create <IOpenIdConnectConfigurationManager>();
            var oidcLoginHandler = new OpenIdConnectLoginHandler(configManager.Object);

            var provider = new OidcIdentityProvider
            {
                Name = "ID Provider " + Guid.NewGuid(),
                IsProviderEnabled = enabled,
                OidcClientId      = clientId,
                OidcClientSecret  = clientSecret,
                OidcIdentityProviderConfigurationUrl = configUrl,
                OidcUserIdentityClaim = claim
            };

            Assert.That(
                async() =>
                await
                oidcLoginHandler.GetAuthorizationCodeRequestUrl(
                    new IdentityProviderLoginRequest {
                IdentityProviderId = provider.Id, Tenant = "EDC", RedirectUrl = "http://test.com"
            }, new Uri("http://test.com")),
                Throws.TypeOf <AuthenticationException>());
        }
Пример #2
0
        public async Task <IHttpActionResult> GetIdentityProviderAuthorizeUrl([FromBody] IdentityProviderLoginRequest idpLoginRequest)
        {
            if (idpLoginRequest == null)
            {
                throw new WebArgumentException("idpLoginRequest", "The identity provider login request is invalid.");
            }

            var oidcLoginHandler = new OpenIdConnectLoginHandler(OpenIdConnectConfigurationManager);

            if (oidcLoginHandler.IsTokenValidationDisabled)
            {
                EventLog.Application.WriteError("OpenIdConnectLoginHandler has token validation disabled. This is not be used in production.");
                throw new AuthenticationException();
            }

            try
            {
                var authorizeUrl = await oidcLoginHandler.GetAuthorizationCodeRequestUrl(idpLoginRequest, new Uri(Request.RequestUri.GetLeftPart(UriPartial.Authority)));

                return(Ok(authorizeUrl.ToString()));
            }
            catch (Exception exception)
            {
                EventLog.Application.WriteError("Failed to get identity provider authorize url. Error: {0}",
                                                exception.ToString());
                throw;
            }
        }
Пример #3
0
        public void ProcessOidcAuthorizationResponse_FailedTokenRequest(string response, HttpStatusCode httpStatusCode, Type exceptionType, string message)
        {
            var context = RequestContext.GetContext();

            OidcIdentityProvider     idProvider;
            OidcIdentityProviderUser idProviderUser;
            UserAccount userAccount;
            string      tenantName = GetCurrentTenantName();

            CreateEntityModel("*****@*****.**", true, out idProvider, out idProviderUser, out userAccount);

            var code = Guid.NewGuid().ToString();

            // Mock config provider and http client

            var errorResponseMessage = new HttpResponseMessage {
                Content = new StringContent(response), StatusCode = httpStatusCode
            };

            var mockRepo      = new MockRepository(MockBehavior.Strict);
            var configUrl     = idProvider.OidcIdentityProviderConfigurationUrl;
            var configManager = mockRepo.Create <IOpenIdConnectConfigurationManager>();

            configManager.Setup(w => w.GetIdentityProviderConfigurationAsync(configUrl)).Returns(Task.FromResult(_oidcConfig));
            configManager.Setup(w => w.RemoveIdentityProviderConfiguration(configUrl));
            var httpClient = mockRepo.Create <IHttpClient>();

            httpClient.Setup(w => w.PostAsync(new Uri(_oidcConfig.TokenEndpoint), It.IsAny <HttpContent>()))
            .Returns(Task.FromResult(errorResponseMessage));

            var oidcLoginHandler = new OpenIdConnectLoginHandler(configManager.Object);

            var idpLoginRequest = new IdentityProviderLoginRequest
            {
                Tenant             = context.Tenant.Name,
                IdentityProviderId = idProvider.Id,
                RedirectUrl        = "https://test.com/login/callback"
            };
            var baseUri = new Uri("https://test.com");

            // Get code auth uri, get state
            var uri = Task.Run(() => oidcLoginHandler.GetAuthorizationCodeRequestUrl(idpLoginRequest, baseUri)).Result;

            var queryValues    = uri.ParseQueryString();
            var state          = queryValues["state"];
            var validatedState = oidcLoginHandler.ValidateAuthState(state);

            Assert.That(
                async() =>
                await
                oidcLoginHandler.ProcessOidcAuthorizationResponse(tenantName, code, validatedState, baseUri, httpClient.Object),
                Throws.TypeOf(exceptionType).And.Message.EqualTo(message));

            mockRepo.VerifyAll();
        }
Пример #4
0
        public void ProcessOidcAuthorizationResponse_InvalidUser(string test)
        {
            var context = RequestContext.GetContext();

            OidcIdentityProvider     idProvider = null;
            OidcIdentityProviderUser idProviderUser;
            UserAccount userAccount;
            string      tenantName = GetCurrentTenantName();

            switch (test)
            {
            case "NoIdpUser":
                // Create user account with a different name
                CreateEntityModel("testUser", true, out idProvider, out idProviderUser, out userAccount);
                break;

            case "NoUserAccount":
                // Create idp user with matching name but without associated account
                CreateEntityModelNoUserAccount("*****@*****.**", out idProvider, out idProviderUser);
                break;

            case "DisabledUserAccount":
                // Create user account with a disabled account
                CreateEntityModel("*****@*****.**", false, out idProvider, out idProviderUser, out userAccount);
                break;
            }

            var code = Guid.NewGuid().ToString();

            // Mock config provider and http client
            var expectedTokenRequestMessage = new OpenIdConnectMessage
            {
                GrantType    = "authorization_code",
                Code         = code,
                ClientSecret = Factory.SecuredData.Read((Guid)idProvider.OidcClientSecretSecureId),
                ClientId     = idProvider.OidcClientId,
                RedirectUri  = "https://test.com/spapi/data/v1/login/oidc/authresponse/" + tenantName
            };

            var validResponseMessage = new HttpResponseMessage {
                Content = new StringContent(_openIdTokenResponse)
            };

            var mockRepo      = new MockRepository(MockBehavior.Strict);
            var configUrl     = idProvider.OidcIdentityProviderConfigurationUrl;
            var configManager = mockRepo.Create <IOpenIdConnectConfigurationManager>();

            configManager.Setup(w => w.GetIdentityProviderConfigurationAsync(configUrl)).Returns(Task.FromResult(_oidcConfig));
            var httpClient = mockRepo.Create <IHttpClient>();

            httpClient.Setup(w => w.PostAsync(new Uri(_oidcConfig.TokenEndpoint), It.Is <HttpContent>(c => ValidateTokenRequestMessage(expectedTokenRequestMessage, c))))
            .Returns(Task.FromResult(validResponseMessage));

            var oidcLoginHandler = new OpenIdConnectLoginHandler(configManager.Object, true);

            var idpLoginRequest = new IdentityProviderLoginRequest
            {
                Tenant             = context.Tenant.Name,
                IdentityProviderId = idProvider.Id,
                RedirectUrl        = "https://test.com/login/callback/"
            };
            var baseUri = new Uri("https://test.com");

            // Get code auth uri, get state
            var uri = Task.Run(() => oidcLoginHandler.GetAuthorizationCodeRequestUrl(idpLoginRequest, baseUri)).Result;

            var queryValues    = uri.ParseQueryString();
            var state          = queryValues["state"];
            var validatedState = oidcLoginHandler.ValidateAuthState(state);

            Assert.That(
                async() =>
                await oidcLoginHandler.ProcessOidcAuthorizationResponse(tenantName, code, validatedState, baseUri, httpClient.Object),
                Throws.TypeOf <AuthenticationException>().And.Message.EqualTo("The request context could not be found. The user name may be incorrect or the account may be locked, disabled or expired."));

            mockRepo.VerifyAll();
        }
Пример #5
0
        public void ProcessOidcAuthorizationResponse_EnabledTokenValidation()
        {
            var context = RequestContext.GetContext();

            OidcIdentityProvider     idProvider;
            OidcIdentityProviderUser idProviderUser;
            UserAccount userAccount;
            string      tenantName = GetCurrentTenantName();

            CreateEntityModel("*****@*****.**", true, out idProvider, out idProviderUser, out userAccount);

            var code = Guid.NewGuid().ToString();

            // Mock config provider and http client
            var expectedTokenRequestMessage = new OpenIdConnectMessage
            {
                GrantType    = "authorization_code",
                Code         = code,
                ClientSecret = Factory.SecuredData.Read((Guid)idProvider.OidcClientSecretSecureId),
                ClientId     = idProvider.OidcClientId,
                RedirectUri  = "https://test.com/spapi/data/v1/login/oidc/authresponse/" + tenantName
            };

            var validResponseMessage = new HttpResponseMessage {
                Content = new StringContent(_openIdTokenResponse)
            };

            var mockRepo      = new MockRepository(MockBehavior.Strict);
            var configUrl     = idProvider.OidcIdentityProviderConfigurationUrl;
            var configManager = mockRepo.Create <IOpenIdConnectConfigurationManager>();

            configManager.Setup(w => w.GetIdentityProviderConfigurationAsync(configUrl)).Returns(Task.FromResult(_oidcConfig));
            configManager.Setup(w => w.RemoveIdentityProviderConfiguration(configUrl));
            var httpClient = mockRepo.Create <IHttpClient>();

            httpClient.Setup(w => w.PostAsync(new Uri(_oidcConfig.TokenEndpoint), It.Is <HttpContent>(c => ValidateTokenRequestMessage(expectedTokenRequestMessage, c))))
            .Returns(Task.FromResult(validResponseMessage));

            var oidcLoginHandler = new OpenIdConnectLoginHandler(configManager.Object);

            var idpLoginRequest = new IdentityProviderLoginRequest
            {
                Tenant             = context.Tenant.Name,
                IdentityProviderId = idProvider.Id,
                RedirectUrl        = "https://test.com/login/callback"
            };
            var baseUri = new Uri("https://test.com");

            // Get code auth uri, get state
            var uri = Task.Run(() => oidcLoginHandler.GetAuthorizationCodeRequestUrl(idpLoginRequest, baseUri)).Result;

            var queryValues    = uri.ParseQueryString();
            var state          = queryValues["state"];
            var validatedState = oidcLoginHandler.ValidateAuthState(state);

            Assert.That(
                async() =>
                await
                oidcLoginHandler.ProcessOidcAuthorizationResponse(tenantName, code, validatedState, baseUri, httpClient.Object),
                Throws.TypeOf <AuthenticationException>());
        }
Пример #6
0
        public void GetAuthorizationCodeRequestUrl_InvalidLoginRequest()
        {
            var mockRepo      = new MockRepository(MockBehavior.Loose);
            var configManager = mockRepo.Create <IOpenIdConnectConfigurationManager>();

            configManager.Setup(w => w.GetIdentityProviderConfigurationAsync(It.IsAny <string>())).Returns(Task.FromResult(_oidcConfig));
            var oidcLoginHandler = new OpenIdConnectLoginHandler(configManager.Object);

            Assert.That(async() => await oidcLoginHandler.GetAuthorizationCodeRequestUrl(new IdentityProviderLoginRequest {
                IdentityProviderId = 0, Tenant = "EDC"
            }, null),
                        Throws.TypeOf <ArgumentNullException>().And.Property("ParamName").EqualTo("requestBaseUrl"));

            Assert.That(
                async() => await oidcLoginHandler.GetAuthorizationCodeRequestUrl(new IdentityProviderLoginRequest {
                IdentityProviderId = 0, Tenant = "EDC", RedirectUrl = ""
            }, null),
                Throws.TypeOf <ArgumentNullException>().And.Property("ParamName").EqualTo("requestBaseUrl"));

            Assert.That(async() => await oidcLoginHandler.GetAuthorizationCodeRequestUrl(null, new Uri("http://test.com")),
                        Throws.TypeOf <ArgumentNullException>().And.Property("ParamName").EqualTo("idpLoginRequest"));

            Assert.That(
                async() =>
                await
                oidcLoginHandler.GetAuthorizationCodeRequestUrl(new IdentityProviderLoginRequest {
                IdentityProviderId = 100, RedirectUrl = "http://test.com"
            },
                                                                new Uri("http://test.com")),
                Throws.TypeOf <ArgumentException>().And.Property("ParamName").EqualTo("idpLoginRequest"));

            Assert.That(
                async() =>
                await
                oidcLoginHandler.GetAuthorizationCodeRequestUrl(new IdentityProviderLoginRequest {
                IdentityProviderId = 0, Tenant = "EDC", RedirectUrl = "http://test.com"
            },
                                                                new Uri("http://test.com")),
                Throws.TypeOf <ArgumentException>().And.Property("ParamName").EqualTo("idpLoginRequest"));

            Assert.That(
                async() =>
                await oidcLoginHandler.GetAuthorizationCodeRequestUrl(new IdentityProviderLoginRequest {
                IdentityProviderId = 0, Tenant = "EDC"
            }, new Uri("http://test.com")),
                Throws.TypeOf <ArgumentException>().And.Property("ParamName").EqualTo("idpLoginRequest"));

            Assert.That(
                async() =>
                await
                oidcLoginHandler.GetAuthorizationCodeRequestUrl(
                    new IdentityProviderLoginRequest {
                IdentityProviderId = 10000, Tenant = "EDC", RedirectUrl = "http://test.com"
            }, new Uri("http://test.com")),
                Throws.TypeOf <AuthenticationException>().And.Message.EqualTo("The identity provider does not exist."));

            Assert.That(
                async() =>
                await
                oidcLoginHandler.GetAuthorizationCodeRequestUrl(
                    new IdentityProviderLoginRequest {
                IdentityProviderId = 10000, Tenant = Guid.NewGuid().ToString(), RedirectUrl = "http://test.com"
            },
                    new Uri("http://test.com")),
                Throws.TypeOf <EntityNotFoundException>());
        }
Пример #7
0
        public void GetAuthorizationCodeRequestUrl()
        {
            var context = RequestContext.GetContext();

            OidcIdentityProvider     idProvider;
            OidcIdentityProviderUser idProviderUser;
            UserAccount userAccount;

            // Setup entity model
            CreateEntityModel("IDP User" + Guid.NewGuid(), false, out idProvider, out idProviderUser, out userAccount);

            // Create mock
            var mockRepo      = new MockRepository(MockBehavior.Strict);
            var configUrl     = idProvider.OidcIdentityProviderConfigurationUrl;
            var configManager = mockRepo.Create <IOpenIdConnectConfigurationManager>();

            configManager.Setup(w => w.GetIdentityProviderConfigurationAsync(configUrl)).Returns(Task.FromResult(_oidcConfig));

            var idpLoginRequest = new IdentityProviderLoginRequest
            {
                Tenant             = context.Tenant.Name,
                IdentityProviderId = idProvider.Id,
                RedirectUrl        = "https://test.com/login/callback"
            };
            var baseUri = new Uri("https://test.com");

            var oidcLoginHandler = new OpenIdConnectLoginHandler(configManager.Object);

            var timeStampBefore = DateTime.UtcNow;

            var uri = Task.Run(() => oidcLoginHandler.GetAuthorizationCodeRequestUrl(idpLoginRequest, baseUri)).Result;

            var timeStampAfter = DateTime.UtcNow;

            // Validate url
            Assert.AreEqual("rndev20adfs.sp.local", uri.Host);
            Assert.AreEqual("/adfs/oauth2/authorize/", uri.AbsolutePath);

            var queryValues = uri.ParseQueryString();

            Assert.AreEqual(idProvider.OidcClientId, queryValues["client_id"], "The client_id is invalid");
            Assert.AreEqual("https://test.com/spapi/data/v1/login/oidc/authresponse/" + context.Tenant.Name.ToLowerInvariant(), queryValues["redirect_uri"], "The redirect_uri is invalid");
            Assert.AreEqual("openid email", queryValues["scope"], "The scope is invalid");
            Assert.AreEqual("code", queryValues["response_type"], "The response_type is invalid");
            Assert.AreEqual("login", queryValues["prompt"], "The prompt is invalid");

            var nonce = queryValues["nonce"];

            Assert.IsNotNullOrEmpty(nonce, "The nonce is invalid.");

            var state = queryValues["state"];

            Assert.IsNotNullOrEmpty(state, "The state is invalid.");

            var validatedState = oidcLoginHandler.ValidateAuthState(state);

            Assert.AreEqual(context.Tenant.Id, validatedState.TenantId, "The state TenantId is invalid");
            Assert.AreEqual(idProvider.Id, validatedState.IdentityProviderId, "The state IdentityProviderId is invalid");
            Assert.AreEqual(nonce, validatedState.Nonce, "The state Nonce is invalid");
            Assert.AreEqual(idpLoginRequest.RedirectUrl, validatedState.RedirectUrl, "The state RedirectUrl is invalid");

            var timeStamp = new DateTime(validatedState.Timestamp, DateTimeKind.Utc);

            // Verify timestamp is between times
            Assert.GreaterOrEqual(timeStamp, timeStampBefore);
            Assert.LessOrEqual(timeStamp, timeStampAfter);

            mockRepo.VerifyAll();
        }