From a25a1939eb10699139920ba7f3303eb240fe86ec Mon Sep 17 00:00:00 2001 From: AnumehaSrivastava05 Date: Wed, 2 Mar 2022 19:46:49 -0700 Subject: [PATCH 1/2] 5511 - Add Org Validation 1. Added Validator 2. Updated SecurityConfig --- .../hnweb/security/OrganizationValidator.java | 56 +++++++++++++++++++ .../hlth/hnweb/security/SecurityConfig.java | 6 +- 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/ca/bc/gov/hlth/hnweb/security/OrganizationValidator.java 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 new file mode 100644 index 00000000..cd942dd1 --- /dev/null +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/OrganizationValidator.java @@ -0,0 +1,56 @@ +package ca.bc.gov.hlth.hnweb.security; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.oauth2.core.OAuth2Error; +import org.springframework.security.oauth2.core.OAuth2ErrorCodes; +import org.springframework.security.oauth2.core.OAuth2TokenValidator; +import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.stereotype.Component; +import org.springframework.util.Assert; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import ca.bc.gov.hlth.hnweb.persistence.entity.Transaction; +import ca.bc.gov.hlth.hnweb.persistence.entity.TransactionEventType; +import ca.bc.gov.hlth.hnweb.service.AuditService; + +@Component +public class OrganizationValidator implements OAuth2TokenValidator { + + private static final Logger logger = LoggerFactory.getLogger(OrganizationValidator.class); + + private static final String CLAIM_ORGANIZATION = "org_details"; + + private static final OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST, " User has no Organization", + "https://tools.ietf.org/html/rfc6750#section-3.1"); + + + @Autowired + private AuditService auditService; + + @Override + public OAuth2TokenValidatorResult validate(Jwt jwt) { + Assert.notNull(jwt, "Token cannot be null"); + + String org = jwt.getClaim(CLAIM_ORGANIZATION); + + if (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. + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + Transaction transaction = auditService.createTransaction(request.getRemoteAddr(), TransactionType.UNKNOWN); + auditService.createTransactionEvent(transaction, TransactionEventType.UNAUTHORIZED); + + logger.info(error.getDescription()); + return OAuth2TokenValidatorResult.failure(error); + } + } +} 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 451654e1..ebedc642 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 @@ -40,6 +40,9 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private AudienceValidator audienceValidator; + @Autowired + private OrganizationValidator organizationValidator; + @Autowired private CustomAccessDeniedHandler accessDeniedHandler; @@ -73,8 +76,9 @@ public JwtDecoder jwtDecoder() { OAuth2TokenValidator withIssuer = JwtValidators.createDefaultWithIssuer(issuerUri); OAuth2TokenValidator withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, audienceValidator); + OAuth2TokenValidator withOrganization = new DelegatingOAuth2TokenValidator<>(withAudience, organizationValidator); - jwtDecoder.setJwtValidator(withAudience); + jwtDecoder.setJwtValidator(withOrganization); return jwtDecoder; } From d1b7af44fefd7ec41a47058a1754e3702fb644f7 Mon Sep 17 00:00:00 2001 From: weskubo-cgi Date: Thu, 3 Mar 2022 16:10:27 -0800 Subject: [PATCH 2/2] Updated logging to make it clearer when there's an error. --- .../bc/gov/hlth/hnweb/security/AudienceValidator.java | 4 ++-- .../hlth/hnweb/security/OrganizationValidator.java | 11 ++++------- .../ca/bc/gov/hlth/hnweb/security/SecurityUtil.java | 4 ++-- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/AudienceValidator.java b/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/AudienceValidator.java index 937a5673..10562086 100644 --- a/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/AudienceValidator.java +++ b/backend/src/main/java/ca/bc/gov/hlth/hnweb/security/AudienceValidator.java @@ -52,8 +52,8 @@ public OAuth2TokenValidatorResult validate(Jwt jwt) { Transaction transaction = auditService.createTransaction(request.getRemoteAddr(), TransactionType.UNKNOWN); auditService.createTransactionEvent(transaction, TransactionEventType.UNAUTHORIZED); - logger.debug(error.getDescription()); + logger.warn("User {} is missing aud claim {} ", jwt.getClaim(SecurityUtil.CLAIM_USERNAME).toString(), audience); return OAuth2TokenValidatorResult.failure(error); } } -} +} \ No newline at end of file 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 cd942dd1..63a9110e 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 @@ -24,13 +24,10 @@ public class OrganizationValidator implements OAuth2TokenValidator { private static final Logger logger = LoggerFactory.getLogger(OrganizationValidator.class); - - private static final String CLAIM_ORGANIZATION = "org_details"; - private static final OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST, " User has no Organization", + private static final OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST, " User has no org_details", "https://tools.ietf.org/html/rfc6750#section-3.1"); - @Autowired private AuditService auditService; @@ -38,7 +35,7 @@ public class OrganizationValidator implements OAuth2TokenValidator { public OAuth2TokenValidatorResult validate(Jwt jwt) { Assert.notNull(jwt, "Token cannot be null"); - String org = jwt.getClaim(CLAIM_ORGANIZATION); + String org = jwt.getClaim(SecurityUtil.CLAIM_ORGANIZATION); if (StringUtils.isNotEmpty(org)) { return OAuth2TokenValidatorResult.success(); @@ -49,8 +46,8 @@ public OAuth2TokenValidatorResult validate(Jwt jwt) { Transaction transaction = auditService.createTransaction(request.getRemoteAddr(), TransactionType.UNKNOWN); auditService.createTransactionEvent(transaction, TransactionEventType.UNAUTHORIZED); - logger.info(error.getDescription()); + logger.warn("User {} has no org_details (Organization)", jwt.getClaim(SecurityUtil.CLAIM_USERNAME).toString()); return OAuth2TokenValidatorResult.failure(error); } } -} +} \ No newline at end of file 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 3a765291..6f594c92 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 @@ -22,8 +22,8 @@ public class SecurityUtil { private static final String CLAIM_RESOURCE_ACCESS = "resource_access"; private static final String CLAIM_SESSION_STATE = "session_state"; - private static final String CLAIM_USERNAME = "preferred_username"; - private static final String CLAIM_ORGANIZATION = "org_details"; + public static final String CLAIM_USERNAME = "preferred_username"; + public static final String CLAIM_ORGANIZATION = "org_details"; private static final String ORGANIZATION_ID = "id";