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"); }
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); }
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."); }
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(); }
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); } }