Exemplo n.º 1
0
        public void ProcessOidcAuthorizationResponse_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);
            string tenantName       = GetCurrentTenantName();

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

            var authState = new OpenIdConnectAuthorizationState
            {
                TenantId           = RequestContext.TenantId,
                IdentityProviderId = provider.Id
            };

            Assert.That(
                async() =>
                await oidcLoginHandler.ProcessOidcAuthorizationResponse(tenantName, "code", authState, new Uri("http://test.com"), new BasicHttpClient()),
                Throws.TypeOf <AuthenticationException>());
        }
        /// <summary>
        /// </summary>
        /// <param name="oidcIdentityProvider"></param>
        // ReSharper disable once UnusedParameter.Local
        private void ValidateOidcProviderFields(OidcIdentityProvider oidcIdentityProvider)
        {
            if (string.IsNullOrWhiteSpace(oidcIdentityProvider.OidcClientId))
            {
                throw new AuthenticationException("The identity provider client id is invalid.");
            }

            if (string.IsNullOrWhiteSpace(oidcIdentityProvider.OidcIdentityProviderConfigurationUrl))
            {
                throw new AuthenticationException("The identity provider configuration url is invalid.");
            }

            if (string.IsNullOrWhiteSpace(oidcIdentityProvider.OidcClientSecret))
            {
                throw new AuthenticationException("The identity provider client secret is invalid.");
            }

            if (string.IsNullOrWhiteSpace(oidcIdentityProvider.OidcUserIdentityClaim))
            {
                throw new AuthenticationException("The identity provider identity claim is invalid.");
            }

            if (!(oidcIdentityProvider.IsProviderEnabled ?? true))
            {
                throw new AuthenticationException("The identity provider is disabled.");
            }
        }
        public void GetValidRequestContextFromCache_UnmappedOidcUser()
        {
            var entitiesToSave = new List <IEntity>();

            // Setup provider, provider user and user account
            var provider = new OidcIdentityProvider {
                Name = "ID Provider " + Guid.NewGuid()
            };

            entitiesToSave.Add(provider);

            var userAccount = new UserAccount {
                Name = "Test User " + Guid.NewGuid(), AccountStatus_Enum = UserAccountStatusEnum_Enumeration.Active
            };

            entitiesToSave.Add(userAccount);

            // Provider user has no associated user account
            var providerUser = new OidcIdentityProviderUser
            {
                Name = "Provider User" + Guid.NewGuid(),
                IdentityProviderForUser = provider.As <IdentityProvider>()
            };

            entitiesToSave.Add(providerUser);

            Entity.Save(entitiesToSave);

            var cache = new IdentityProviderContextCache();
            var requestContextData = cache.GetRequestContextData(RequestContext.TenantId, provider.Id, providerUser.Name, true);

            Assert.IsNull(requestContextData, "Context data should be null");
        }
Exemplo n.º 4
0
        private void CreateEntityModel(string idpUserName, bool active, out OidcIdentityProvider idProvider, out OidcIdentityProviderUser idProviderUser, out UserAccount userAccount)
        {
            var entitiesToSave = new List <IEntity>();

            // Setup provider, provider user and user account
            idProvider = new OidcIdentityProvider
            {
                Name = "ID Provider " + Guid.NewGuid(),
                IsProviderEnabled = true,
                OidcClientId      = "5E9762FD-8EB8-4626-AB5A-A52A05041DC0",
                OidcClientSecret  = "cZ7xNZiBvPB41Clw0i0FnR4LRqfHvj2H3tBt6c8l",
                OidcIdentityProviderConfigurationUrl = "https://rndev20adfs.sp.local/adfs/.well-known/openid-configuration",
                OidcUserIdentityClaim = "upn"
            };
            entitiesToSave.Add(idProvider);

            userAccount = new UserAccount {
                Name = "Test User " + Guid.NewGuid(), AccountStatus_Enum = active ? UserAccountStatusEnum_Enumeration.Active : UserAccountStatusEnum_Enumeration.Disabled
            };
            entitiesToSave.Add(userAccount);

            idProviderUser = new OidcIdentityProviderUser
            {
                AssociatedUserAccount = userAccount,
                Name = idpUserName,
                IdentityProviderForUser = idProvider.As <IdentityProvider>()
            };
            entitiesToSave.Add(idProviderUser);

            Entity.Save(entitiesToSave);
        }
Exemplo n.º 5
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>());
        }
        public void GetValidRequestContextFromCache_DisabledToActiveUserAccount()
        {
            var entitiesToSave = new List <IEntity>();

            // Setup provider, provider user and user account
            var provider = new OidcIdentityProvider {
                Name = "ID Provider " + Guid.NewGuid()
            };

            entitiesToSave.Add(provider);

            var userAccount = new UserAccount {
                Name = "Test User " + Guid.NewGuid(), AccountStatus_Enum = UserAccountStatusEnum_Enumeration.Disabled
            };

            entitiesToSave.Add(userAccount);

            // Provider user has no associated user account
            var providerUser = new OidcIdentityProviderUser
            {
                AssociatedUserAccount = userAccount,
                Name = "Provider User" + Guid.NewGuid(),
                IdentityProviderForUser = provider.As <IdentityProvider>()
            };

            entitiesToSave.Add(providerUser);

            Entity.Save(entitiesToSave);

            var cache = new IdentityProviderContextCache();
            var requestContextData = cache.GetRequestContextData(RequestContext.TenantId, provider.Id, providerUser.Name, false);

            Assert.IsNotNull(requestContextData, "Context data should not be null");

            requestContextData = cache.GetRequestContextData(RequestContext.TenantId, provider.Id, providerUser.Name, true);

            Assert.IsNull(requestContextData, "Context data should be null");

            // Change the account to active
            userAccount.AccountStatus_Enum = UserAccountStatusEnum_Enumeration.Active;
            userAccount.Save();

            cache.CacheInvalidator.OnEntityChange(new IEntity[] { userAccount }, InvalidationCause.Save, null);

            requestContextData = cache.GetRequestContextData(RequestContext.TenantId, provider.Id, providerUser.Name, true);

            Assert.IsNotNull(requestContextData, "Context data should not be null");
        }
        public void DeleteIdp(OidcIdentityProvider idp, ClaimsPrincipal user)
        {
            if (idp == null)
            {
                throw new Exception("Identity provider was not provided.");
            }

            authorizationLogic.IsAuthorizedThrowsException(AuthorizationScopes.ManageIdentityProviders, user, idp);

            if (!configurationRepository.Exists <OidcIdentityProvider>(idp.Id))
            {
                throw new Exception("Identity provider does not exist");
            }

            configurationRepository.Delete <OidcIdentityProvider>(idp.Id);
        }
        public void GetValidRequestContextFromCache_OidcProviderInvalidateOnUserChange()
        {
            var entitiesToSave = new List <IEntity>();

            // Setup provider, provider user and user account
            var provider = new OidcIdentityProvider {
                Name = "ID Provider " + Guid.NewGuid()
            };

            entitiesToSave.Add(provider);

            var userAccount = new UserAccount {
                Name = "Test User " + Guid.NewGuid(), AccountStatus_Enum = UserAccountStatusEnum_Enumeration.Active
            };

            entitiesToSave.Add(userAccount);

            var providerUser = new OidcIdentityProviderUser
            {
                AssociatedUserAccount = userAccount,
                Name = "Provider User" + Guid.NewGuid(),
                IdentityProviderForUser = provider.As <IdentityProvider>()
            };

            entitiesToSave.Add(providerUser);

            Entity.Save(entitiesToSave);

            var cache = new IdentityProviderContextCache();
            var requestContextData = cache.GetRequestContextData(RequestContext.TenantId, provider.Id, providerUser.Name, true);

            Assert.IsNotNull(requestContextData, "Context data should not be null.");
            Assert.AreEqual(userAccount.Id, requestContextData.Identity.Id, "The context identity user id is invalid.");
            Assert.AreEqual(userAccount.Name, requestContextData.Identity.Name, "The context identity user name is invalid.");
            Assert.AreEqual(provider.Id, requestContextData.Identity.IdentityProviderId, "The context identity provider is invalid.");
            Assert.AreEqual(providerUser.Id, requestContextData.Identity.IdentityProviderUserId, "The context identity provider user id is invalid.");
            Assert.AreEqual(provider.IsOfType[0].Alias, requestContextData.Identity.IdentityProviderTypeAlias, "The context identity provider alias is invalid.");

            // This should invalidate the cache
            providerUser.AssociatedUserAccount = null;
            providerUser.Save();

            cache.CacheInvalidator.OnEntityChange(new IEntity[] { providerUser }, InvalidationCause.Save, null);

            requestContextData = cache.GetRequestContextData(RequestContext.TenantId, provider.Id, providerUser.Name, true);
            Assert.IsNull(requestContextData, "Context data should be null.");
        }
        public void AddIdp(OidcIdentityProvider idp, ClaimsPrincipal user)
        {
            try
            {
                new System.Uri(idp.Authority);
            }
            catch
            {
                throw new ObjectNotInCorrectStateException("Authority must be a well formed base URL without the well-known oidc path");
            }

            if (string.IsNullOrEmpty(idp.ClientId) || string.IsNullOrEmpty(idp.Name))
            {
                throw new ObjectNotInCorrectStateException("Client Id and Name must be provided for this Idp");
            }

            configurationRepository.Insert <OidcIdentityProvider>(idp);
        }
        public void OAuthUpgrade()
        {
            var oip       = new OidcIdentityProvider();
            var oldSecret = "Test" + DateTime.UtcNow.Ticks;

            oip.OidcClientSecret = _crypto.EncryptAndEncode(oldSecret);

            using (var scope = Factory.Current.BeginLifetimeScope(builder => builder.RegisterType <SecuredDataSaveHelper.DisabledSaveHelper>().As <ISecuredDataSaveHelper>()))
                using (Factory.SetCurrentScope(scope))
                {
                    oip.Save();
                }

            SecureDataUpgradeHelper.Upgrade("EDC");

            var secureId = oip.OidcClientSecretSecureId;

            Assert.That(secureId, Is.Not.Null);
            var secret = Factory.SecuredData.Read((Guid)secureId);

            Assert.That(secret, Is.EqualTo(oldSecret));
        }
 public JsonResult AddOidcIdentityProvider(OidcIdentityProvider idp)
 {
     oidcLogic.AddIdp(idp, User);
     return(http.RespondSuccess());
 }
 public JsonResult DeleteOidcIdentityProvider(OidcIdentityProvider idp)
 {
     oidcLogic.DeleteIdp(idp, User);
     return(http.RespondSuccess("Identity Provider deleted successfully"));
 }
        public void GetIdentityProvidersValidTenantTest(bool enabled)
        {
            var oidcProvider1 = new OidcIdentityProvider
            {
                Name = "TestProvider1 " + Guid.NewGuid(),
                IsProviderEnabled = enabled,
                ProviderOrdinal   = 100
            };

            oidcProvider1.Save();

            var oidcProvider2 = new OidcIdentityProvider
            {
                Name = "TestProvider2 " + Guid.NewGuid(),
                IsProviderEnabled = enabled,
                ProviderOrdinal   = 200
            };

            oidcProvider2.Save();

            var idpRepository = new IdentityProviderRepository();
            var context       = RequestContext.GetContext();
            var providers     = idpRepository.GetIdentityProviders(context.Tenant.Name);

            Assert.IsNotNull(providers, "Providers response should not be null.");
            Assert.AreEqual(enabled ? 3 : 1, providers.IdentityProviders.Count, "The providers count is invalid.");

            var provider1 = providers.IdentityProviders.FirstOrDefault(i => i.Id == oidcProvider1.Id);

            if (enabled)
            {
                Assert.IsNotNull(provider1, "Provider 1 was not found.");
                Assert.AreEqual(oidcProvider1.Name, provider1.Name, "Provider 1 name is invalid.");
                Assert.AreEqual(oidcProvider1.ProviderOrdinal, provider1.Ordinal, "Provider 1 ordinal is invalid.");
                Assert.AreEqual(oidcProvider1.IsOfType[0].Alias, provider1.TypeAlias, "Provider 1 type alias is invalid.");
            }
            else
            {
                Assert.IsNull(provider1, "Provider 1 was found.");
            }

            var provider2 = providers.IdentityProviders.FirstOrDefault(i => i.Id == oidcProvider2.Id);

            if (enabled)
            {
                Assert.IsNotNull(provider2, "Provider 2 was not found.");
                Assert.AreEqual(oidcProvider2.Name, provider2.Name, "Provider 2 name is invalid.");
                Assert.AreEqual(oidcProvider2.ProviderOrdinal, provider2.Ordinal, "Provider 2 ordinal is invalid.");
                Assert.AreEqual(oidcProvider2.IsOfType[0].Alias, provider2.TypeAlias, "Provider 2 type alias is invalid.");
            }
            else
            {
                Assert.IsNull(provider2, "Provider 2 was found.");
            }

            var readiNowProviderEntity = Entity.Get <ReadiNowIdentityProvider>(WellKnownAliases.CurrentTenant.ReadiNowIdentityProviderInstance);

            var readiNowProvider = providers.IdentityProviders.FirstOrDefault(i => i.Id == readiNowProviderEntity.Id);

            Assert.IsNotNull(readiNowProvider, "ReadiNow provider was not found.");
            Assert.AreEqual(readiNowProviderEntity.Name, readiNowProvider.Name, "ReadiNow provider name is invalid.");
            Assert.AreEqual(readiNowProviderEntity.ProviderOrdinal, readiNowProvider.Ordinal, "ReadiNow provider ordinal is invalid.");
            Assert.AreEqual(readiNowProviderEntity.IsOfType[0].Alias, readiNowProvider.TypeAlias, "ReadiNow provider type alias is invalid.");
        }
Exemplo n.º 14
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();
        }
Exemplo n.º 15
0
        public void ProcessOidcAuthorizationResponse()
        {
            var context = RequestContext.GetContext();

            OidcIdentityProvider     idProvider     = null;
            OidcIdentityProviderUser idProviderUser = null;
            UserAccount userAccount = null;

            try
            {
                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));
                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);

                var result =
                    Task.Run(() => oidcLoginHandler.ProcessOidcAuthorizationResponse(tenantName, code, validatedState, baseUri, httpClient.Object)).Result;

                Assert.IsNotNull(result, "The authorization result is invalid.");
                Assert.IsNotNull(result.RequestContextData, "The authorization result context data is invalid.");
                Assert.IsNotNull(result.IdentityProviderUserName, "The authorization result user name is invalid.");

                Assert.AreEqual(RequestContext.TenantId, result.RequestContextData.Tenant.Id, "The tenant is invalid");
                Assert.AreEqual(userAccount.Id, result.RequestContextData.Identity.Id, "The user account is invalid");
                Assert.AreEqual(idProvider.Id, result.RequestContextData.Identity.IdentityProviderId, "The identity provider id is invalid");
                Assert.AreEqual(userAccount.Name, result.RequestContextData.Identity.Name, "The identity provider id is invalid");
                Assert.AreEqual(idProviderUser.Name, result.IdentityProviderUserName, "The identity provider id is invalid");

                mockRepo.VerifyAll();
            }
            finally
            {
                DeleteEntity(idProvider);
                DeleteEntity(idProviderUser);
                DeleteEntity(userAccount);
            }
        }