diff --git a/app/server/src/main/java/com/appsmith/server/configurations/ClientUserRepository.java b/app/server/src/main/java/com/appsmith/server/configurations/ClientUserRepository.java index 51599ecd58..748327269f 100644 --- a/app/server/src/main/java/com/appsmith/server/configurations/ClientUserRepository.java +++ b/app/server/src/main/java/com/appsmith/server/configurations/ClientUserRepository.java @@ -3,6 +3,8 @@ package com.appsmith.server.configurations; import com.appsmith.server.domains.LoginSource; import com.appsmith.server.domains.User; import com.appsmith.server.domains.UserState; +import com.appsmith.server.exceptions.AppsmithError; +import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.UserService; import org.springframework.context.annotation.Configuration; @@ -10,7 +12,9 @@ import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; import org.springframework.security.oauth2.client.web.server.WebSessionServerOAuth2AuthorizedClientRepository; +import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser; import org.springframework.security.oauth2.core.oidc.user.OidcUser; +import org.springframework.stereotype.Component; import org.springframework.util.Assert; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebSession; @@ -39,18 +43,24 @@ import java.util.Map; * saveAuthorizedClient is called on every successful OAuth2 authentication, this solves the problem * of plugging a handler for the same purpose. */ -@Configuration +@Component public class ClientUserRepository implements ServerOAuth2AuthorizedClientRepository { private static final String DEFAULT_AUTHORIZED_CLIENTS_ATTR_NAME = WebSessionServerOAuth2AuthorizedClientRepository.class.getName() + ".AUTHORIZED_CLIENTS"; + private final String sessionAttributeName = DEFAULT_AUTHORIZED_CLIENTS_ATTR_NAME; + UserService userService; + OrganizationService organizationService; - public ClientUserRepository(UserService userService, OrganizationService organizationService) { + CommonConfig commonConfig; + + public ClientUserRepository(UserService userService, OrganizationService organizationService, CommonConfig commonConfig) { this.userService = userService; this.organizationService = organizationService; + this.commonConfig = commonConfig; } @Override @@ -69,6 +79,19 @@ public class ClientUserRepository implements ServerOAuth2AuthorizedClientReposit ServerWebExchange exchange) { Assert.notNull(authorizedClient, "authorizedClient cannot be null"); Assert.notNull(exchange, "exchange cannot be null"); + Assert.notNull(principal, "authentication object cannot be null"); + + // Check if the list of configured custom domains match the authenticated principal. + // This is to provide more control over which accounts can be used to access the application. + // TODO: This is not a good way to do this. Ideally, we should pass "hd=example.com" to OAuth2 provider to list relevant accounts only + if(!commonConfig.getAllowedDomains().isEmpty()) { + DefaultOidcUser userPrincipal = (DefaultOidcUser) principal.getPrincipal(); + String domain = (String) userPrincipal.getAttributes().getOrDefault("hd", ""); + if(!commonConfig.getAllowedDomains().contains(domain)) { + return Mono.error(new AppsmithException(AppsmithError.UNAUTHORIZED_DOMAIN)); + } + } + return exchange.getSession() .doOnSuccess(session -> { Map authorizedClients = getAuthorizedClients(session); diff --git a/app/server/src/main/java/com/appsmith/server/configurations/CommonConfig.java b/app/server/src/main/java/com/appsmith/server/configurations/CommonConfig.java index 4a76935c88..beb9220219 100644 --- a/app/server/src/main/java/com/appsmith/server/configurations/CommonConfig.java +++ b/app/server/src/main/java/com/appsmith/server/configurations/CommonConfig.java @@ -1,5 +1,8 @@ package com.appsmith.server.configurations; +import lombok.Getter; +import lombok.Setter; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import reactor.core.scheduler.Scheduler; @@ -7,12 +10,18 @@ import reactor.core.scheduler.Schedulers; import javax.validation.Validation; import javax.validation.Validator; +import java.util.List; +@Getter +@Setter @Configuration public class CommonConfig { private String ELASTIC_THREAD_POOL_NAME = "appsmith-elastic-pool"; + @Value("#{'${oauth2.allowed-domains}'.split(',')}") + private List allowedDomains; + @Bean public Scheduler scheduler() { return Schedulers.newElastic(ELASTIC_THREAD_POOL_NAME); diff --git a/app/server/src/main/java/com/appsmith/server/configurations/SecurityConfig.java b/app/server/src/main/java/com/appsmith/server/configurations/SecurityConfig.java index f1a540afaa..cf0e18c520 100644 --- a/app/server/src/main/java/com/appsmith/server/configurations/SecurityConfig.java +++ b/app/server/src/main/java/com/appsmith/server/configurations/SecurityConfig.java @@ -29,6 +29,9 @@ public class SecurityConfig { @Autowired private OrganizationService organizationService; + @Autowired + private CommonConfig commonConfig; + /** * This configuration enables CORS requests for the most common HTTP Methods * @@ -72,7 +75,7 @@ public class SecurityConfig { .authenticated() .and().httpBasic() .and().oauth2Login() - .authorizedClientRepository(new ClientUserRepository(userService, organizationService)) + .authorizedClientRepository(new ClientUserRepository(userService, organizationService, commonConfig)) .and().formLogin() .and().build(); } diff --git a/app/server/src/main/java/com/appsmith/server/exceptions/AppsmithError.java b/app/server/src/main/java/com/appsmith/server/exceptions/AppsmithError.java index 62fbc48cbb..b337b17ab1 100644 --- a/app/server/src/main/java/com/appsmith/server/exceptions/AppsmithError.java +++ b/app/server/src/main/java/com/appsmith/server/exceptions/AppsmithError.java @@ -12,6 +12,7 @@ public enum AppsmithError { PLUGIN_NOT_INSTALLED(400, 4001, "Plugin {0} not installed"), PLUGIN_ID_NOT_GIVEN(400, 4002, "Missing plugin id. Please input correct plugin id"), RESOURCE_ID_NOT_GIVEN(400, 4003, "Missing resource id. Please input correct resource id"), + UNAUTHORIZED_DOMAIN(401, 4001, "Invalid email domain provided. Please sign in with a valid work email ID"), INTERNAL_SERVER_ERROR(500, 5000, "Internal server error while processing request"); private Integer httpErrorCode; diff --git a/app/server/src/main/resources/application-local.properties b/app/server/src/main/resources/application-local.properties index a137604007..573b245504 100644 --- a/app/server/src/main/resources/application-local.properties +++ b/app/server/src/main/resources/application-local.properties @@ -19,5 +19,5 @@ jdbc.postgres.password=root spring.security.oauth2.client.registration.google.client-id=869021686091-9b84bbf7ea683t1aaefqnmefcnmk6fq6.apps.googleusercontent.com spring.security.oauth2.client.registration.google.client-secret=9dvITt4OayEY1HfeY8bHX74p -#Hard coded organization properties -organization.id=5d64f1f594a5d31b3ee9ca16 +# Accounts from specific domains are allowed to login +oauth2.allowed-domains=appsmith.com \ No newline at end of file diff --git a/app/server/src/main/resources/application-staging.properties b/app/server/src/main/resources/application-staging.properties index 308607bf98..d986eba6ef 100644 --- a/app/server/src/main/resources/application-staging.properties +++ b/app/server/src/main/resources/application-staging.properties @@ -17,5 +17,5 @@ jdbc.postgres.password=09275163cd7e737baf4c210b5e8db8ed88ddb7a0ee9acc82416fd7534 spring.security.oauth2.client.registration.google.client-id=869021686091-9b84bbf7ea683t1aaefqnmefcnmk6fq6.apps.googleusercontent.com spring.security.oauth2.client.registration.google.client-secret=9dvITt4OayEY1HfeY8bHX74p -#Hard coded organization properties -organization.id=5d3e90a2dfec7c00047a81ea +# Accounts from specific domains are allowed to login +oauth2.allowed-domains=appsmith.com \ No newline at end of file diff --git a/app/server/src/main/resources/application.properties b/app/server/src/main/resources/application.properties index e618a2e827..c3064f6a2a 100644 --- a/app/server/src/main/resources/application.properties +++ b/app/server/src/main/resources/application.properties @@ -12,7 +12,4 @@ spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults=false spring.jpa.show-sql=true # Jackson Properties -spring.jackson.default-property-inclusion=non_null - -#Hard coded organization properties -organization.id=5d5e7c29006cb4e82ea75075 \ No newline at end of file +spring.jackson.default-property-inclusion=non_null \ No newline at end of file