diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/OrganizationValidator.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/OrganizationValidator.java index 63a9110e..d9f784e9 100644 --- a/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/OrganizationValidator.java +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/OrganizationValidator.java @@ -37,7 +37,8 @@ public OAuth2TokenValidatorResult validate(Jwt jwt) { String org = jwt.getClaim(SecurityUtil.CLAIM_ORGANIZATION); - if (StringUtils.isNotEmpty(org)) { + // Service accounts won't have an Organization so don't validate + if (SecurityUtil.isServiceAccount(jwt) || StringUtils.isNotEmpty(org)) { return OAuth2TokenValidatorResult.success(); } else { // Audit the failure. Only users with defined Organization should be considered as authorized and able to access MSP Direct. diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/SecurityConfig.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/SecurityConfig.java index 98e60784..ab4481ce 100644 --- a/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/SecurityConfig.java +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/SecurityConfig.java @@ -81,10 +81,10 @@ protected void configure(HttpSecurity http) throws Exception { .mvcMatchers(HttpMethod.POST, "/msp-contracts/update-contract-address").hasRole("UpdateContractAddress") .mvcMatchers(HttpMethod.POST, "/msp-contracts/inquire-contract").hasAnyRole("ContractInquiry", "GetContractAddress") //inquire-contract endpoint will require this multi role as it is used by both R40 and R37 transactions .mvcMatchers(HttpMethod.POST, "/patient-registration/get-patient-registration").hasRole("PatientRegistration") - .mvcMatchers(HttpMethod.GET, "/payee-mapping/").hasAnyRole("PatientRegistration", "ManageMSPPayeeNumber") + .mvcMatchers(HttpMethod.GET, "/payee-mapping/{id}").hasAnyRole("PatientRegistration", "ManageMSPPayeeNumber") .mvcMatchers(HttpMethod.POST, "/payee-mapping").hasRole("ManageMSPPayeeNumber") - .mvcMatchers(HttpMethod.PUT, "/payee-mapping/").hasRole("ManageMSPPayeeNumber") - .mvcMatchers(HttpMethod.DELETE, "/payee-mapping/").hasRole("ManageMSPPayeeNumber") + .mvcMatchers(HttpMethod.PUT, "/payee-mapping/{id}").hasRole("ManageMSPPayeeNumber") + .mvcMatchers(HttpMethod.DELETE, "/payee-mapping/{id}").hasRole("ManageMSPPayeeNumber") .mvcMatchers(HttpMethod.GET, "/user/**").fullyAuthenticated() .mvcMatchers("/*").denyAll() .and() diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/SecurityUtil.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/SecurityUtil.java index 6eee3943..7b10ba36 100644 --- a/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/SecurityUtil.java +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/SecurityUtil.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.Map; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -28,6 +29,7 @@ public class SecurityUtil { public static final String CLAIM_USERNAME = "preferred_username"; private static final String CLAIM_SUB = "sub"; // the Subject claim identifies the principal that is the subject of the JWT public static final String CLAIM_ORGANIZATION = "org_details"; + public static final String CLAIM_CLIENT_ID = "clientId"; private static final String ORGANIZATION_ID = "id"; @@ -37,6 +39,8 @@ public class SecurityUtil { private static final String UNKNOWN_ROLE = "UNKNOWN"; + private static final String SERVICE_SUFFIX = "-SERVICE"; + private static String KEYCLOAK_CLIENT; private static SecurityProperties securityProperties; @@ -167,5 +171,17 @@ public static List loadPermissions(Jwt jwt, Map> ro return permissions; } + + /** + * Checks if the jwt is generated for a service account. + * @param jwt + * @return + */ + public static Boolean isServiceAccount(Jwt jwt) { + // This is just a rough check to see if the client is a service account + // It's good enough to detect any current MSP Direct API clients + return StringUtils.endsWith(jwt.getClaim(SecurityUtil.CLAIM_CLIENT_ID), SERVICE_SUFFIX); + + } } \ No newline at end of file