Skip to content

Commit 1d53a37

Browse files
authored
Cognito domain creation and expose OAuth to frontend config (#756)
* fix: default domain and expose oauth to config * chore: update integration snapshots * chore: update integration snapshots * chore: add changeset * chore: temporary domain randomness * fix: make domainPrefix a prop * chore: update snapshots * chore: add changeset * chore: fix lint * chore: add tests for oauth output and error handling * fix: if domain is not specified, do not output domain * chore: update api * chore: fix lint * chore: cleanup * chore: update test * chore: only allow configuring domainPrefix if external providers are listed
1 parent 967df2a commit 1d53a37

File tree

17 files changed

+454
-36
lines changed

17 files changed

+454
-36
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@aws-amplify/backend-output-schemas': patch
3+
'@aws-amplify/integration-tests': patch
4+
'@aws-amplify/auth-construct-alpha': patch
5+
'create-amplify': patch
6+
'@aws-amplify/client-config': patch
7+
'@aws-amplify/backend-auth': patch
8+
---
9+
10+
Cognito domains are now created by default, and oauth settings are exported to frontend config.

.changeset/twenty-spies-smile.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@aws-amplify/backend-output-schemas': minor
3+
'@aws-amplify/integration-tests': minor
4+
'@aws-amplify/auth-construct-alpha': minor
5+
'create-amplify': minor
6+
'@aws-amplify/client-config': minor
7+
'@aws-amplify/backend-auth': minor
8+
---
9+
10+
Expose domainPrefix as an input property to the Auth construct.

.eslint_dictionary.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[
22
"aggregator",
33
"amazonaws",
4+
"amazoncognito",
45
"amplifyconfiguration",
56
"appleid",
67
"appsync",

packages/auth-construct/API.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@ export type ExternalProviderOptions = {
6060
oidc?: OidcProviderProps;
6161
saml?: SamlProviderProps;
6262
scopes?: ('PHONE' | 'EMAIL' | 'OPENID' | 'PROFILE' | 'COGNITO_ADMIN')[];
63-
callbackUrls?: string[];
64-
logoutUrls?: string[];
63+
callbackUrls: string[];
64+
domainPrefix?: string;
65+
logoutUrls: string[];
6566
};
6667

6768
// @public

packages/auth-construct/src/construct.test.ts

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,66 @@ void describe('Auth construct', () => {
498498
]);
499499
});
500500

501+
void it('stores outputs in platform - oauth config', () => {
502+
const authConstruct = new AmplifyAuth(stack, 'test', {
503+
loginWith: {
504+
email: true,
505+
externalProviders: {
506+
google: {
507+
clientId: googleClientId,
508+
clientSecret: SecretValue.unsafePlainText(googleClientSecret),
509+
},
510+
scopes: ['EMAIL', 'PROFILE'],
511+
callbackUrls: ['http://callback.com'],
512+
logoutUrls: ['http://logout.com'],
513+
domainPrefix: 'test-prefix',
514+
},
515+
},
516+
outputStorageStrategy: stubBackendOutputStorageStrategy,
517+
});
518+
519+
const expectedUserPoolId = (
520+
authConstruct.node.findChild('UserPool') as UserPool
521+
).userPoolId;
522+
const expectedIdentityPoolId = (
523+
authConstruct.node.findChild('IdentityPool') as CfnIdentityPool
524+
).ref;
525+
const expectedWebClientId = (
526+
authConstruct.node.findChild('UserPoolAppClient') as UserPoolClient
527+
).userPoolClientId;
528+
const expectedRegion = Stack.of(authConstruct).region;
529+
530+
const storeOutputArgs = storeOutputMock.mock.calls[0].arguments;
531+
assert.equal(storeOutputArgs.length, 2);
532+
533+
assert.deepStrictEqual(storeOutputArgs, [
534+
authOutputKey,
535+
{
536+
version: '1',
537+
payload: {
538+
userPoolId: expectedUserPoolId,
539+
webClientId: expectedWebClientId,
540+
identityPoolId: expectedIdentityPoolId,
541+
authRegion: expectedRegion,
542+
passwordPolicyMinLength:
543+
DEFAULTS.PASSWORD_POLICY.minLength.toString(),
544+
passwordPolicyRequirements:
545+
defaultPasswordPolicyCharacterRequirements,
546+
signupAttributes: '["EMAIL"]',
547+
verificationMechanisms: '["EMAIL"]',
548+
usernameAttributes: '["EMAIL"]',
549+
googleClientId: 'googleClientId',
550+
oauthDomain: `test-prefix.auth.${expectedRegion}.amazoncognito.com`,
551+
oauthScope: '["email","profile"]',
552+
oauthRedirectSignIn: 'http://callback.com',
553+
oauthRedirectSignOut: 'http://logout.com',
554+
oauthResponseType: 'code',
555+
socialProviders: '["GOOGLE"]',
556+
},
557+
},
558+
]);
559+
});
560+
501561
void it('multifactor prop updates mfaConfiguration & mfaTypes', () => {
502562
new AmplifyAuth(stack, 'test', {
503563
loginWith: {
@@ -914,6 +974,8 @@ void describe('Auth construct', () => {
914974
clientId: googleClientId,
915975
clientSecret: SecretValue.unsafePlainText(googleClientSecret),
916976
},
977+
callbackUrls: ['https://redirect.com'],
978+
logoutUrls: ['https://logout.com'],
917979
},
918980
},
919981
});
@@ -943,6 +1005,8 @@ void describe('Auth construct', () => {
9431005
clientId: googleClientId,
9441006
clientSecret: SecretValue.unsafePlainText(googleClientSecret),
9451007
},
1008+
callbackUrls: ['https://redirect.com'],
1009+
logoutUrls: ['https://logout.com'],
9461010
},
9471011
},
9481012
});
@@ -972,6 +1036,8 @@ void describe('Auth construct', () => {
9721036
clientId: facebookClientId,
9731037
clientSecret: facebookClientSecret,
9741038
},
1039+
callbackUrls: ['https://redirect.com'],
1040+
logoutUrls: ['https://logout.com'],
9751041
},
9761042
},
9771043
});
@@ -1001,6 +1067,8 @@ void describe('Auth construct', () => {
10011067
clientId: facebookClientId,
10021068
clientSecret: facebookClientSecret,
10031069
},
1070+
callbackUrls: ['https://redirect.com'],
1071+
logoutUrls: ['https://logout.com'],
10041072
},
10051073
},
10061074
});
@@ -1032,6 +1100,8 @@ void describe('Auth construct', () => {
10321100
privateKey: applePrivateKey,
10331101
teamId: appleTeamId,
10341102
},
1103+
callbackUrls: ['https://redirect.com'],
1104+
logoutUrls: ['https://logout.com'],
10351105
},
10361106
},
10371107
});
@@ -1063,6 +1133,8 @@ void describe('Auth construct', () => {
10631133
privateKey: applePrivateKey,
10641134
teamId: appleTeamId,
10651135
},
1136+
callbackUrls: ['https://redirect.com'],
1137+
logoutUrls: ['https://logout.com'],
10661138
},
10671139
},
10681140
});
@@ -1092,6 +1164,8 @@ void describe('Auth construct', () => {
10921164
clientId: amazonClientId,
10931165
clientSecret: amazonClientSecret,
10941166
},
1167+
callbackUrls: ['https://redirect.com'],
1168+
logoutUrls: ['https://logout.com'],
10951169
},
10961170
},
10971171
});
@@ -1121,6 +1195,8 @@ void describe('Auth construct', () => {
11211195
clientId: amazonClientId,
11221196
clientSecret: amazonClientSecret,
11231197
},
1198+
callbackUrls: ['https://redirect.com'],
1199+
logoutUrls: ['https://logout.com'],
11241200
},
11251201
},
11261202
});
@@ -1152,6 +1228,8 @@ void describe('Auth construct', () => {
11521228
issuerUrl: oidcIssuerUrl,
11531229
name: oidcProviderName,
11541230
},
1231+
callbackUrls: ['https://redirect.com'],
1232+
logoutUrls: ['https://logout.com'],
11551233
},
11561234
},
11571235
});
@@ -1197,6 +1275,8 @@ void describe('Auth construct', () => {
11971275
issuerUrl: oidcIssuerUrl,
11981276
name: oidcProviderName,
11991277
},
1278+
callbackUrls: ['https://redirect.com'],
1279+
logoutUrls: ['https://logout.com'],
12001280
},
12011281
},
12021282
});
@@ -1243,6 +1323,8 @@ void describe('Auth construct', () => {
12431323
metadataType: UserPoolIdentityProviderSamlMetadataType.FILE,
12441324
},
12451325
},
1326+
callbackUrls: ['https://redirect.com'],
1327+
logoutUrls: ['https://logout.com'],
12461328
},
12471329
},
12481330
});
@@ -1287,6 +1369,8 @@ void describe('Auth construct', () => {
12871369
metadataType: UserPoolIdentityProviderSamlMetadataType.FILE,
12881370
},
12891371
},
1372+
callbackUrls: ['https://redirect.com'],
1373+
logoutUrls: ['https://logout.com'],
12901374
},
12911375
},
12921376
});
@@ -1357,6 +1441,81 @@ void describe('Auth construct', () => {
13571441
});
13581442
});
13591443

1444+
void it('throws an error if callbackUrls are not specified with external login providers', () => {
1445+
const app = new App();
1446+
const stack = new Stack(app);
1447+
assert.throws(
1448+
() =>
1449+
new AmplifyAuth(stack, 'test', {
1450+
loginWith: {
1451+
email: true,
1452+
externalProviders: {
1453+
google: {
1454+
clientId: googleClientId,
1455+
clientSecret: SecretValue.unsafePlainText(googleClientSecret),
1456+
},
1457+
scopes: ['EMAIL', 'PROFILE'],
1458+
callbackUrls: [],
1459+
logoutUrls: ['http://localhost'],
1460+
},
1461+
},
1462+
}),
1463+
{
1464+
message:
1465+
'You must define callbackUrls when configuring external login providers.',
1466+
}
1467+
);
1468+
});
1469+
1470+
void it('throws an error if logoutUrls are not specified with external login providers', () => {
1471+
const app = new App();
1472+
const stack = new Stack(app);
1473+
assert.throws(
1474+
() =>
1475+
new AmplifyAuth(stack, 'test', {
1476+
loginWith: {
1477+
email: true,
1478+
externalProviders: {
1479+
google: {
1480+
clientId: googleClientId,
1481+
clientSecret: SecretValue.unsafePlainText(googleClientSecret),
1482+
},
1483+
scopes: ['EMAIL', 'PROFILE'],
1484+
callbackUrls: ['http://redirect.com'],
1485+
logoutUrls: [],
1486+
},
1487+
},
1488+
}),
1489+
{
1490+
message:
1491+
'You must define logoutUrls when configuring external login providers.',
1492+
}
1493+
);
1494+
});
1495+
1496+
void it('throws an error if domainPrefix is configured without any external providers', () => {
1497+
const app = new App();
1498+
const stack = new Stack(app);
1499+
assert.throws(
1500+
() =>
1501+
new AmplifyAuth(stack, 'test', {
1502+
loginWith: {
1503+
email: true,
1504+
externalProviders: {
1505+
scopes: ['EMAIL', 'PROFILE'],
1506+
callbackUrls: [],
1507+
logoutUrls: ['http://localhost'],
1508+
domainPrefix: 'https://localhost',
1509+
},
1510+
},
1511+
}),
1512+
{
1513+
message:
1514+
'You cannot configure a domain prefix if there are no external providers configured.',
1515+
}
1516+
);
1517+
});
1518+
13601519
void it('supports all idps and login methods', () => {
13611520
const app = new App();
13621521
const stack = new Stack(app);
@@ -1396,6 +1555,8 @@ void describe('Auth construct', () => {
13961555
metadataType: UserPoolIdentityProviderSamlMetadataType.FILE,
13971556
},
13981557
},
1558+
callbackUrls: ['https://redirect.com'],
1559+
logoutUrls: ['https://logout.com'],
13991560
},
14001561
},
14011562
});

0 commit comments

Comments
 (0)