Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ATO-745: Identity Support For User Info #111

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

BenjaminWCO
Copy link
Contributor

@BenjaminWCO BenjaminWCO commented Sep 19, 2024

  • Added config controller request body validation
  • Added support to configure claim data from config controller
  • Added support to return claim data from user info controller
  • Added CoreIdentityJWT generation (vot and vc fields can be configured via config controller)
  • Removed HMRC specific InheritedIdentityJWT claim

BAU:

  • Removed unnecessary dependancy on "body-parser"
  • Fixed typos

@BenjaminWCO BenjaminWCO requested review from a team as code owners September 19, 2024 16:20
@BenjaminWCO BenjaminWCO force-pushed the ATO-745-Identity-For-User-Info branch 7 times, most recently from db5fc9d to 64f59e4 Compare September 19, 2024 16:58
@CarlyG55 CarlyG55 force-pushed the ATO-745-Identity-For-User-Info branch from 64f59e4 to 0a6d93c Compare September 19, 2024 17:08
@BenjaminWCO BenjaminWCO marked this pull request as draft September 23, 2024 09:30
@CarlyG55
Copy link
Collaborator

Can you remove the return codes validation? Since we definitely won't be validating these

src/config.ts Outdated
Comment on lines 48 to 81
this.clientId = process.env.CLIENT_ID ?? "HGIOgho9HIRhgoepdIOPFdIUWgewi0jw";
this.publicKey = process.env.PUBLIC_KEY ?? defaultPublicKey;
this.scopes = process.env.SCOPES
? process.env.SCOPES.split(",")
: ["openid", "email", "phone"];
this.redirectUrls = process.env.REDIRECT_URLS
? process.env.REDIRECT_URLS.split(",")
: ["http://localhost:8080/authorization-code/callback"];
this.claims = process.env.CLAIMS
? (process.env.CLAIMS.split(",") as (keyof UserIdentity)[])
: ["https://vocab.account.gov.uk/v1/coreIdentityJWT"];
this.identityVerificationSupported =
process.env.IDENTITY_VERIFICATION_SUPPORTED !== "false";
this.idTokenSigningAlgorithm =
process.env.ID_TOKEN_SIGNING_ALGORITHM ?? "ES256";
this.clientLoCs = process.env.CLIENT_LOCS
? process.env.CLIENT_LOCS.split(",")
: ["P0", "P2"];

this.sub =
process.env.SUB ??
"urn:fdc:gov.uk:2022:56P4CMsGh_02YOlWpd8PAOI-2sVlB2nsNU7mcLZYhYw=";
this.email = process.env.EMAIL ?? "john.smith@gmail.com";
this.emailVerified = process.env.EMAIL_VERIFIED !== "false";
this.phoneNumber = process.env.PHONE_NUMBER ?? "07123456789";
this.phoneNumberVerified = process.env.PHONE_NUMBER_VERIFIED !== "false";

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason we moved from the more nested structure that was introduced here?https://github.com/govuk-one-login/simulator/pull/46/files

Copy link
Contributor Author

@BenjaminWCO BenjaminWCO Sep 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason is that some properties may be optional in the config request, but must have a value (i.e. some default) so the types don't necessarily align. I suppose an alternative might be to fall back to the defaults from the setters rather than setting them in the constructor. Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted this. Using "!" assertion in getters when needed.

src/components/user-info/user-info-controller.ts Outdated Show resolved Hide resolved
src/components/user-info/user-info-controller.ts Outdated Show resolved Hide resolved
export const generateDrivingPermitPropertyValidators = (
parent?: string
): ValidationChain[] => {
const prefix = parent ? `${parent}.` : "";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do these property validators ever have the value of parent passed in? It looks like they don't, if so we could simplify the code a bit. Appreciate I may be missing something here, so happy to be told otherwise 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if this is a good pattern, but it was the best way I could think of. Most of the time it is set, because you have to describe the full chain of properties from the root object. The only case it's unset is for the root object (so ConfigRequest). ConfigRequest could simply not take the optional parameter and all the other types could require it. The reason for duplicating the prefix logic for all the types is just for a consistent pattern. Potentially useful If you had a type that could appear in different locations in a request body.

tests/integration/config.test.ts Outdated Show resolved Hide resolved
}

export const generateClientConfigurationPropertyValidators = (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not super familiar with these validators, they seem pretty readable, but some tests for these might be nice 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a few examples in the config integration test. We could add some more thorough tests, tough I'm not sure what the best way to do that would be. Given the way express-validator runs as a middleware, the simplest way would be to add a bunch more test cases to the config endpoint integration test, but given it's an endpoint that's in a state of flux at the moment that might be quite brittle.

Copy link
Contributor Author

@BenjaminWCO BenjaminWCO Sep 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could come up with some tests helper function that spins up an express server with some test endpoint and pass in the validator to that. That might be a nice way to test validating each type individually.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've adde the helper function and some individual tests for validated types.

.isURL()
.optional({ values: "null" }),
body(`${prefix}${nameof<Identity>("sub")}`)
.isURL()
Copy link
Contributor

@Ryan-Andrews99 Ryan-Andrews99 Sep 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quite a few of these the isURL method called, I wouldn't expect most of them to be valid URLs. Is this correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're right - iss and sub should just validated to be strings.

Copy link
Contributor Author

@BenjaminWCO BenjaminWCO Oct 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed this type as coreIdentityJWT is being generated now

Comment on lines 95 to 151
if (
validationResult.claims?.includes(
"https://vocab.account.gov.uk/v1/inheritedIdentityJWT"
)
) {
const inheritedIdentity = config.getInheritedIdentityDetails();
userInfo["https://vocab.account.gov.uk/v1/inheritedIdentityJWT"] =
await new SignJWT(inheritedIdentity as any)
.setProtectedHeader({
alg: "ES256",
})
.sign(signingKey);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not something that is returned in the user info endpoint. This is a slight abuse of the spec for HMRC to pass us additional information about a user

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

Copy link
Member

@ethanmills ethanmills left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm really hesitant about the amount of validation we're doing here. We don't own the schema for the validations we're performing, and there's no way to ensure this stays correct and up to date. I happen to know, for example, that new fields will soon be valid in address objects. There's no real way for us to test that this validation matches the information returned by One Login. In general I think we should avoid providing functionality unless we can be confident that we can ensure it stays correct.

userInfo["https://vocab.account.gov.uk/v1/coreIdentityJWT"] =
await new SignJWT(coreIdentity as any)
.setProtectedHeader({
alg: "ES256",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think we're missing a kid here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Comment on lines 6 to 14
vot?: string;
vtm?: string;
iss?: string;
sub?: string;
nbf?: number;
exp?: number;
aud?: string;
iat?: number;
jti?: string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we missing vc?

Copy link
Contributor Author

@BenjaminWCO BenjaminWCO Oct 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added - vot and vc are configurable. The other fields are now generated.

Comment on lines 6 to 14
vot?: string;
vtm?: string;
iss?: string;
sub?: string;
nbf?: number;
exp?: number;
aud?: string;
iat?: number;
jti?: string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels like we should be setting some sensible defaults for some of these?

Copy link
Contributor Author

@BenjaminWCO BenjaminWCO Oct 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above - vot and vc are configurable. The other fields are now generated.

@BenjaminWCO BenjaminWCO force-pushed the ATO-745-Identity-For-User-Info branch 2 times, most recently from 8b1ffb1 to ddd20b9 Compare October 1, 2024 17:17
@BenjaminWCO BenjaminWCO force-pushed the ATO-745-Identity-For-User-Info branch from ddd20b9 to 1c5dd66 Compare October 1, 2024 17:18
Copy link

sonarcloud bot commented Oct 1, 2024

Quality Gate Failed Quality Gate failed

Failed conditions
4.7% Duplication on New Code (required ≤ 3%)
1 New Code Smells (required ≤ 0)

See analysis details on SonarCloud

Catch issues before they fail your Quality Gate with our IDE extension SonarLint

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants