Skip to content

Commit 9493d8f

Browse files
Merge branch 'develop' into renovate/webpack-5.x-lockfile
2 parents b14bc7d + d6f7f39 commit 9493d8f

File tree

16 files changed

+1366
-3069
lines changed

16 files changed

+1366
-3069
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
version: 2.1
22
orbs:
3-
cypress: cypress-io/[email protected].0
3+
cypress: cypress-io/[email protected].1
44
codecov: codecov/[email protected] #
55

66
executors:

.env

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ VITE_BACKEND_PORT=3001
3131
#VITE_OKTA_DOMAIN="dev-your-domain-id.okta.com"
3232
#VITE_OKTA_CLIENTID="your-client-id"
3333

34-
# AWS Cognito #Okta Configuration to be added to .env when running "yarn dev:cognito"
34+
# AWS Cognito Configuration to be added to .env when running "yarn dev:cognito"
3535
# Additional config taken from aws-exports.js
3636
#AWS_COGNITO_USERNAME="[email protected]"
3737
#AWS_COGNITO_PASSWORD="s3cret1234$"
38-
#AWS_COGNITO_DOMAIN="https://YOUR_COGNITO_INSTANCE.auth.us-east-1.amazoncognito.com"
38+
#AWS_COGNITO_DOMAIN="https://YOUR_COGNITO_USER_POOL_HOSTED_UI_DOMAIN_PREFIX.auth.us-east-1.amazoncognito.com"
3939

4040
# Google Auth Configuration to be added to .env when running "yarn dev:google"
4141
# client ID should look something like <identifier>.apps.googleusercontent.com

README.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,26 @@ A [guide has been written with detail around adapting the RWA](http://on.cypress
221221
222222
Prerequisites include an [Amazon Cognito][cognito] account. Environment variables from [Amazon Cognito][cognito] are provided by the [AWS Amplify CLI][awsamplify].
223223
224-
To start the application with Cognito, replace the current **src/index.tsx** file with the **src/index.cognito.tsx** file and start the application with `yarn dev:cognito` and run Cypress with `yarn cypress:open`.
224+
- A user pool is required (identity pool is not used here)
225+
- The user pool must have a hosted UI domain configured, which must:
226+
- allow callback and sign-out URLs of `http://localhost:3000/`,
227+
- allow implicit grant Oauth grant type,
228+
- allow these OpenID Connect scopes:
229+
- aws.cognito.signin.user.admin
230+
- email
231+
- openid
232+
- The user pool must have an app client configured, with:
233+
- enabled auth flow `ALLOW_USER_PASSWORD_AUTH`, only for programmatic login flavor of test.
234+
- The `cy.origin()` flavor of test only requires auth flow `ALLOW_USER_SRP_AUTH`, and does not require `ALLOW_USER_PASSWORD_AUTH`.
235+
- The user pool must have a user corresponding to the `AWS_COGNITO` env vars mentioned below, and the user's Confirmation Status must be `Confirmed`. If it is `Force Reset Password`, then use a browser to log in once at `http://localhost:3000` while `yarn dev:cognito` is running to reset their password.
236+
237+
The test knobs are in a few places:
238+
239+
- The `.env` file has `VITE_AUTH_TOKEN_NAME` and vars beginning `AWS_COGNITO`. Be careful not to commit any secrets.
240+
- Both `scripts/mock-aws-exports.js` and `scripts/mock-aws-exports-es5.js` must have the same data; only their export statements differ. These files can be edited manually or exported from the amplify CLI.
241+
- `cypress.config.ts` has `cognito_programmatic_login` to control flavor of the test.
242+
243+
To start the application with Cognito, replace the current **src/index.tsx** file with the **src/index.cognito.tsx** file and start the application with `yarn dev:cognito` and run Cypress with `yarn cypress:open`. `yarn dev` may need to have been run once first.
225244
226245
The **only passing spec on this branch** will be the [cognito spec](./cypress/tests/ui-auth-providers/cognito.spec.ts); all others will fail.
227246

backend/helpers.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,14 @@ export const verifyOktaToken = (req: Request, res: Response, next: NextFunction)
8080

8181
// Amazon Cognito Validate the JWT Signature
8282
// https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-verifying-a-jwt.html#amazon-cognito-user-pools-using-tokens-step-2
83+
const userPoolId = awsConfig.Auth.Cognito.userPoolId;
84+
const region = userPoolId.split("_")[0];
8385
const awsCognitoJwtConfig = {
8486
secret: jwksRsa.expressJwtSecret({
85-
jwksUri: `https://cognito-idp.${awsConfig.aws_cognito_region}.amazonaws.com/${awsConfig.aws_user_pools_id}/.well-known/jwks.json`,
87+
jwksUri: `https://cognito-idp.${region}.amazonaws.com/${userPoolId}/.well-known/jwks.json`,
8688
}),
8789

88-
issuer: `https://cognito-idp.${awsConfig.aws_cognito_region}.amazonaws.com/${awsConfig.aws_user_pools_id}`,
90+
issuer: `https://cognito-idp.${region}.amazonaws.com/${userPoolId}`,
8991
algorithms: ["RS256"],
9092
};
9193

cypress/support/auth-provider-commands/cognito.ts

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,44 @@
1-
import { Amplify, Auth } from "aws-amplify";
1+
import { Amplify } from "aws-amplify";
2+
import { fetchAuthSession, signIn } from "aws-amplify/auth";
23

34
Amplify.configure(Cypress.env("awsConfig"));
45

6+
const fetchJwts = async (username: string, password: string) => {
7+
const options = { authFlowType: "USER_PASSWORD_AUTH" as const };
8+
await signIn({ username, password, options });
9+
const authSession = await fetchAuthSession();
10+
const tokens = authSession.tokens!;
11+
const accessToken = tokens.accessToken;
12+
const accessTokenPayload = accessToken.payload;
13+
return {
14+
idToken: tokens.idToken!.toString(),
15+
accessToken: accessToken.toString(),
16+
clientId: accessTokenPayload.client_id as string,
17+
accessTokenSub: accessTokenPayload.sub!,
18+
};
19+
};
20+
type JwtResponse = Awaited<ReturnType<typeof fetchJwts>>;
21+
522
// Amazon Cognito
6-
Cypress.Commands.add("loginByCognitoApi", (username, password) => {
23+
Cypress.Commands.add("loginByCognitoApi", (username: string, password: string) => {
724
const log = Cypress.log({
825
displayName: "COGNITO LOGIN",
926
message: [`🔐 Authenticating | ${username}`],
10-
// @ts-ignore
1127
autoEnd: false,
1228
});
1329

1430
log.snapshot("before");
1531

16-
const signIn = Auth.signIn({ username, password });
32+
cy.wrap(fetchJwts(username, password), { log: false }).then((unknownJwts) => {
33+
const { idToken, accessToken, clientId, accessTokenSub } = unknownJwts as JwtResponse;
1734

18-
cy.wrap(signIn, { log: false }).then((cognitoResponse: any) => {
19-
const keyPrefixWithUsername = `${cognitoResponse.keyPrefix}.${cognitoResponse.username}`;
20-
window.localStorage.setItem(
21-
`${keyPrefixWithUsername}.idToken`,
22-
cognitoResponse.signInUserSession.idToken.jwtToken
23-
);
24-
window.localStorage.setItem(
25-
`${keyPrefixWithUsername}.accessToken`,
26-
cognitoResponse.signInUserSession.accessToken.jwtToken
27-
);
28-
window.localStorage.setItem(
29-
`${keyPrefixWithUsername}.refreshToken`,
30-
cognitoResponse.signInUserSession.refreshToken.token
31-
);
32-
window.localStorage.setItem(
33-
`${keyPrefixWithUsername}.clockDrift`,
34-
cognitoResponse.signInUserSession.clockDrift
35-
);
36-
window.localStorage.setItem(
37-
`${cognitoResponse.keyPrefix}.LastAuthUser`,
38-
cognitoResponse.username
39-
);
35+
const keyPrefix = `CognitoIdentityServiceProvider.${clientId}`;
36+
const keyPrefixWithUsername = `${keyPrefix}.${accessTokenSub}`;
4037

41-
window.localStorage.setItem("amplify-authenticator-authState", "signedIn");
38+
const ls = window.localStorage;
39+
ls.setItem(`${keyPrefixWithUsername}.idToken`, idToken);
40+
ls.setItem(`${keyPrefixWithUsername}.accessToken`, accessToken);
41+
ls.setItem(`${keyPrefix}.LastAuthUser`, accessTokenSub);
4242

4343
log.snapshot("after");
4444
log.end();
@@ -60,9 +60,6 @@ Cypress.Commands.add("loginByCognito", (username, password) => {
6060
});
6161

6262
cy.visit("/");
63-
cy.contains("Sign in with AWS", {
64-
includeShadowDom: true,
65-
}).click();
6663

6764
cy.origin(
6865
Cypress.env("cognito_domain"),
@@ -73,6 +70,7 @@ Cypress.Commands.add("loginByCognito", (username, password) => {
7370
},
7471
},
7572
({ username, password }) => {
73+
cy.contains("Sign in with your email and password");
7674
// cognito log in page has some elements of the same id but are off screen. we only want the visible elements to log in
7775
cy.get('input[name="username"]:visible').type(username);
7876
cy.get('input[name="password"]:visible').type(password, {

cypress/tests/ui-auth-providers/cognito.spec.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import "../../support/auth-provider-commands/cognito";
22
import { isMobile } from "../../support/utils";
3+
const apiGraphQL = `${Cypress.env("apiUrl")}/graphql`;
34

45
if (Cypress.env("cognito_username")) {
56
// Sign in with AWS
67
if (Cypress.env("cognito_programmatic_login")) {
7-
describe("AWS Cognito", function () {
8+
describe("AWS Cognito, programmatic login (cypress.config.ts#cognito_programmatic_login: true)", function () {
89
beforeEach(function () {
910
cy.task("db:seed");
1011

11-
cy.intercept("POST", "/bankAccounts").as("createBankAccount");
12+
cy.intercept("POST", apiGraphQL).as("createBankAccount");
1213

1314
cy.loginByCognitoApi(Cypress.env("cognito_username"), Cypress.env("cognito_password"));
1415
});
@@ -49,7 +50,7 @@ if (Cypress.env("cognito_username")) {
4950
});
5051
});
5152
} else {
52-
describe("AWS Cognito", function () {
53+
describe("AWS Cognito, cy.origin() login (cypress.config.ts#cognito_programmatic_login: false)", function () {
5354
beforeEach(function () {
5455
cy.task("db:seed");
5556
cy.loginByCognito(Cypress.env("cognito_username"), Cypress.env("cognito_password"));

package.json

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,12 @@
1212
"url": "https://github.com/cypress-io/cypress-realworld-app/issues"
1313
},
1414
"dependencies": {
15-
"@auth0/auth0-react": "2.1.1",
16-
"@aws-amplify/ui-react": "^5.0.4",
15+
"@auth0/auth0-react": "2.2.4",
1716
"@babel/core": "7.23.9",
1817
"@babel/plugin-syntax-flow": "^7.14.5",
1918
"@babel/plugin-transform-react-jsx": "^7.14.9",
20-
"@graphql-tools/graphql-file-loader": "7.3.10",
21-
"@graphql-tools/load": "7.5.9",
19+
"@graphql-tools/graphql-file-loader": "7.5.17",
20+
"@graphql-tools/load": "7.8.14",
2221
"@material-ui/core": "4.12.4",
2322
"@material-ui/icons": "4.11.3",
2423
"@material-ui/lab": "4.0.0-alpha.61",
@@ -27,14 +26,14 @@
2726
"@okta/okta-auth-js": "^7.3.0",
2827
"@okta/okta-react": "^6.7.0",
2928
"@types/detect-port": "^1.3.2",
30-
"@xstate/react": "3.0.0",
31-
"aws-amplify": "^5.3.3",
32-
"axios": "0.26.1",
33-
"clsx": "1.1.1",
34-
"date-fns": "2.28.0",
29+
"@xstate/react": "3.2.2",
30+
"aws-amplify": "^6.0.16",
31+
"axios": "0.28.0",
32+
"clsx": "1.2.1",
33+
"date-fns": "2.30.0",
3534
"detect-port": "^1.5.1",
3635
"dinero.js": "1.9.1",
37-
"formik": "2.2.9",
36+
"formik": "2.4.5",
3837
"history": "4.10.1",
3938
"postinstall-postinstall": "^2.1.0",
4039
"react": "18.2.0",
@@ -47,7 +46,7 @@
4746
"shortid": "2.2.16",
4847
"uuid": "8.3.2",
4948
"webpack": "5",
50-
"xstate": "4.35.4",
49+
"xstate": "4.38.3",
5150
"yup": "0.32.11"
5251
},
5352
"devDependencies": {
@@ -103,7 +102,7 @@
103102
"eslint-config-react-app": "^7.0.1",
104103
"eslint-plugin-cypress": "2.15.1",
105104
"eslint-plugin-prettier": "^5.0.0",
106-
"express": "4.18.2",
105+
"express": "4.18.3",
107106
"express-graphql": "0.12.0",
108107
"express-jwt": "6.1.2",
109108
"express-paginate": "1.0.2",
@@ -114,7 +113,7 @@
114113
"graphql-tools": "8.2.7",
115114
"http-proxy-middleware": "0.19.1",
116115
"husky": "7.0.4",
117-
"istanbul-lib-coverage": "3.2.0",
116+
"istanbul-lib-coverage": "3.2.2",
118117
"jsdom": "^22.1.0",
119118
"json": "11.0.0",
120119
"jwks-rsa": "2.0.5",

scripts/mock-aws-exports-es5.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,21 @@
11
// mock aws-exports-es5.js
22

33
const awsmobile = {
4-
aws_cognito_region: "",
5-
aws_user_pools_id: "",
4+
Auth: {
5+
Cognito: {
6+
userPoolId: "us-east-1_abcdefghi",
7+
userPoolClientId: "a1b2c3d4e5f6g7h8i9j0k1l2m",
8+
loginWith: {
9+
oauth: {
10+
domain: "YOUR_COGNITO_USER_POOL_HOSTED_UI_DOMAIN_PREFIX.auth.us-east-1.amazoncognito.com",
11+
scopes: ["email", "openid", "aws.cognito.signin.user.admin"],
12+
redirectSignIn: ["http://localhost:3000/"],
13+
redirectSignOut: ["http://localhost:3000/"],
14+
responseType: "token",
15+
},
16+
},
17+
},
18+
},
619
};
720

821
exports.default = awsmobile;

scripts/mock-aws-exports.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,21 @@
11
// mock aws-exports.js
22

33
const awsmobile = {
4-
aws_cognito_region: "",
5-
aws_user_pools_id: "",
4+
Auth: {
5+
Cognito: {
6+
userPoolId: "us-east-1_abcdefghi",
7+
userPoolClientId: "a1b2c3d4e5f6g7h8i9j0k1l2m",
8+
loginWith: {
9+
oauth: {
10+
domain: "YOUR_COGNITO_USER_POOL_HOSTED_UI_DOMAIN_PREFIX.auth.us-east-1.amazoncognito.com",
11+
scopes: ["email", "openid", "aws.cognito.signin.user.admin"],
12+
redirectSignIn: ["http://localhost:3000/"],
13+
redirectSignOut: ["http://localhost:3000/"],
14+
responseType: "token",
15+
},
16+
},
17+
},
18+
},
619
};
720

821
export default awsmobile;

0 commit comments

Comments
 (0)