Skip to content

Commit

Permalink
Adding the unified user accounts code
Browse files Browse the repository at this point in the history
  • Loading branch information
GavCookAND committed Mar 29, 2023
1 parent 3799ec3 commit bf13620
Show file tree
Hide file tree
Showing 17 changed files with 129 additions and 368 deletions.
1 change: 1 addition & 0 deletions .github/workflows/feature.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ jobs:
format: "HTML"
args: >
--enableRetired
--disableOssIndex true
- name: Upload Test results
uses: actions/upload-artifact@master
with:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/imageBuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ jobs:
format: "HTML"
args: >
--enableRetired
--disableOssIndex true
- name: Upload Test results
uses: actions/upload-artifact@master
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ build/
### VS Code ###
.vscode/

application-local.properties
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package gov.cabinetoffice.gap.applybackend.config;

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.cognitoidp.AWSCognitoIdentityProvider;
import com.amazonaws.services.cognitoidp.AWSCognitoIdentityProviderClientBuilder;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import gov.cabinetoffice.gap.applybackend.config.properties.GovNotifyProperties;
import lombok.RequiredArgsConstructor;
Expand All @@ -21,7 +17,6 @@
@Configuration
public class BeanConfig {

private final CognitoConfigProperties cognitoProps;
private final GovNotifyProperties notifyProperties;

@Bean
Expand Down Expand Up @@ -53,16 +48,6 @@ public PhoneNumberUtil getPhoneNumberUtil() {
return PhoneNumberUtil.getInstance();
}

@Bean
public AWSCognitoIdentityProvider getCognitoClientBuilder() {
final BasicAWSCredentials awsCredentials = new BasicAWSCredentials(cognitoProps.getAccessKey(), cognitoProps.getSecretKey());
return AWSCognitoIdentityProviderClientBuilder
.standard()
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.withRegion(cognitoProps.getRegion())
.build();
}

@Bean
public NotificationClient notificationClient() {
return new NotificationClient(notifyProperties.getApiKey());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,12 @@
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Configuration("cognitoConfigurationProperties")
@ConfigurationProperties(prefix = "cognito")
public class CognitoConfigProperties {

@NotNull
private String secretKey;

@NotNull
private String accessKey;

@NotNull
private String region;

@NotNull
private String userPoolId;

@NotNull
private String userPassword;

@Configuration("userServiceConfigurationProperties")
@ConfigurationProperties(prefix = "user-service")
public class UserServiceConfig {
@NotNull
private String domain;

@NotNull
private String appClientId;

private String cookieName;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ public class JwtPayload {
private String eventId;
private String tokenUse;
private String phoneNumber;
private int authTime;
private int exp;
private int iat;
private String familyName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,54 @@
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class UpdateGrantApplicantOrganisationProfileDto {
@Size(max = 250, message = "Organisation name must be 250 characters or less")
@Pattern(regexp = "^(?![\\s\\S])|^[a-zA-Z0-9\\s',-]+$",
message = "Organisation name must only use letters, numbers, and special characters such as hyphens, spaces and apostrophes")
private String legalName;

private GrantApplicantOrganisationType type;

@Size(max = 250, message = "Address line 1 must be 250 characters or less")
@Pattern(regexp = "^(?![\\s\\S])|^[a-zA-Z0-9\\s',-]+$",
message = "Address line 1 must only use letters, numbers, and special characters such as hyphens, spaces and apostrophes")
private String addressLine1;

@Size(max = 250, message = "Address line 2 must be 250 characters or less")
@Pattern(regexp = "^(?![\\s\\S])|^[a-zA-Z0-9\\s',-]+$",
message = "Address line 2 must only use letters, numbers, and special characters such as hyphens, spaces and apostrophes")
private String addressLine2;

@Size(max = 250, message = "Town or City must be 250 characters or less")
@Pattern(regexp = "^(?![\\s\\S])|^[a-zA-Z0-9\\s',-]+$",
message = "Town or City must only use letters, numbers, and special characters such as hyphens, spaces and apostrophes")
private String town;

@Size(max = 250, message = "County must be 250 characters or less")
@Pattern(regexp = "^(?![\\s\\S])|^[a-zA-Z0-9\\s',-]+$",
message = "County must only use letters, numbers, and special characters such as hyphens, spaces and apostrophes")
private String county;

@Size(max = 8, message = "Postcode must be 8 characters or less")
@Pattern(regexp = "^(?![\\s\\S])|^[a-zA-Z0-9\\s',-]+$",
message = "Postcode must only use letters, numbers, and special characters such as hyphens, spaces and apostrophes")
private String postcode;

@Size(max = 250, message = "Charity commission number must be 250 characters or less")
@Pattern(regexp = "^(?![\\s\\S])|^[a-zA-Z0-9\\s',-]+$",
message = "Charity commission number must only use letters, numbers, and special characters such as hyphens, spaces and apostrophes")
private String charityCommissionNumber;

@Size(max = 250, message = "Companies house number must be 250 characters or less")
@Pattern(regexp = "^(?![\\s\\S])|^[a-zA-Z0-9\\s',-]+$",
message = "Companies house must only use letters, numbers, and special characters such as hyphens, spaces and apostrophes")
private String companiesHouseNumber;

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package gov.cabinetoffice.gap.applybackend.security;

import com.auth0.jwk.JwkException;
import com.auth0.jwt.interfaces.DecodedJWT;
import gov.cabinetoffice.gap.applybackend.dto.api.JwtPayload;
import gov.cabinetoffice.gap.applybackend.exception.JwkNotValidTokenException;
import gov.cabinetoffice.gap.applybackend.service.JwtService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
Expand Down Expand Up @@ -44,15 +42,12 @@ protected void doFilterInternal(HttpServletRequest request,
}
//verify the token
String normalisedJwt = header.split(" ")[1];
DecodedJWT decodedJWT = jwtService.decodedJwt(normalisedJwt);
try {
if (!jwtService.verifyToken(decodedJWT)) {
chain.doFilter(request, response);
return;
}
} catch (JwkException e) {
throw new JwkNotValidTokenException("Token not valid");
if (!jwtService.verifyToken(normalisedJwt)) {
chain.doFilter(request, response);
return;
}

DecodedJWT decodedJWT = jwtService.decodedJwt(normalisedJwt);
//set the Security context, so we can access it everywhere
JwtPayload jwtPayload = jwtService.decodeTheTokenPayloadInAReadableFormat(decodedJWT);

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,49 +1,45 @@
package gov.cabinetoffice.gap.applybackend.service;

import com.auth0.jwk.Jwk;
import com.auth0.jwk.JwkException;
import com.auth0.jwk.JwkProvider;
import com.auth0.jwk.UrlJwkProvider;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import gov.cabinetoffice.gap.applybackend.config.CognitoConfigProperties;
import gov.cabinetoffice.gap.applybackend.config.UserServiceConfig;
import gov.cabinetoffice.gap.applybackend.dto.api.JwtPayload;
import gov.cabinetoffice.gap.applybackend.exception.JwkNotValidTokenException;
import static java.lang.Boolean.TRUE;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.StringUtils;
import org.json.JSONObject;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.security.interfaces.RSAPublicKey;
import java.util.Calendar;

@Slf4j
@RequiredArgsConstructor
@Service
public class JwtService {
private final CognitoConfigProperties cognitoProps;

private final UserServiceConfig userServiceConfig;
private final RestTemplate restTemplate;

public DecodedJWT decodedJwt(String normalisedJWT) {
return JWT.decode(normalisedJWT);
}

public boolean verifyToken(DecodedJWT jwt) throws JwkException {
if (isTokenExpired(jwt)) {
return false;
}

boolean isExpectedIssuer = jwt.getIssuer().equals(cognitoProps.getDomain());
boolean isExpectedAud = jwt.getAudience().get(0).equals(cognitoProps.getAppClientId());
if (!isExpectedAud || !isExpectedIssuer) {
throw new JwkNotValidTokenException("Token is not valid");
}
JwkProvider provider = new UrlJwkProvider(cognitoProps.getDomain());
Jwk jwk = provider.get(jwt.getKeyId());
Algorithm algorithm = Algorithm.RSA256((RSAPublicKey) jwk.getPublicKey(), null);
algorithm.verify(jwt);
public boolean verifyToken(final String jwt) {
final String url = userServiceConfig.getDomain() + "/is-user-logged-in";
final HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Cookie", userServiceConfig.getCookieName() + "=" + jwt);
final HttpEntity<String> requestEntity = new HttpEntity<>(null, requestHeaders);
final ResponseEntity<Boolean> isJwtValid = restTemplate.exchange(url, HttpMethod.GET, requestEntity, Boolean.class);
log.info("is user logged in: " + isJwtValid);

return true;
return TRUE.equals(isJwtValid.getBody());
}

public String decodeBase64ToJson(final String base64) {
Expand All @@ -68,7 +64,6 @@ public JwtPayload decodeTheTokenPayloadInAReadableFormat(DecodedJWT jwt) {
final String eventId = jsonObject.getString("event_id");
final String tokenUse = jsonObject.getString("token_use");
final String phoneNumber = jsonObject.getString("custom:phoneNumber");
final int authTime = jsonObject.getInt("auth_time");
final int exp = jsonObject.getInt("exp");
final int iat = jsonObject.getInt("iat");
final String familyName = jsonObject.getString("family_name");
Expand All @@ -85,7 +80,6 @@ public JwtPayload decodeTheTokenPayloadInAReadableFormat(DecodedJWT jwt) {
.eventId(eventId)
.tokenUse(tokenUse)
.phoneNumber(phoneNumber)
.authTime(authTime)
.exp(exp)
.iat(iat)
.familyName(familyName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import gov.cabinetoffice.gap.applybackend.exception.NotFoundException;
import gov.cabinetoffice.gap.applybackend.model.GrantApplicant;
import gov.cabinetoffice.gap.applybackend.model.GrantApplicantOrganisationProfile;
import gov.cabinetoffice.gap.applybackend.model.RegisterApplicant;
import gov.cabinetoffice.gap.applybackend.service.CreateGrantApplicantService;
import gov.cabinetoffice.gap.applybackend.service.GrantApplicantOrganisationProfileService;
import gov.cabinetoffice.gap.applybackend.service.GrantApplicantService;
import io.swagger.v3.oas.annotations.media.Content;
Expand All @@ -20,7 +18,6 @@
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.UUID;

@RequiredArgsConstructor
Expand All @@ -29,7 +26,6 @@
public class GrantApplicantController {

private final GrantApplicantService grantApplicantService;
private final CreateGrantApplicantService createGrantApplicantService;
private final GrantApplicantOrganisationProfileService grantApplicantOrganisationProfileService;
private final ModelMapper modelMapper;

Expand Down Expand Up @@ -83,12 +79,4 @@ public ResponseEntity<String> createApplicant(){

return ResponseEntity.ok("User has been created");
}


@PostMapping("/register")
public ResponseEntity<String> registerApplicant(@Valid @RequestBody RegisterApplicant registerApplicant) {
createGrantApplicantService.createNewUser(registerApplicant);
String response = "User has been created";
return ResponseEntity.ok(response);
}
}
Loading

0 comments on commit bf13620

Please sign in to comment.