Skip to content

Commit

Permalink
feat(amplify-category-auth): configure siwa with cli
Browse files Browse the repository at this point in the history
  • Loading branch information
David Lopez committed May 9, 2021
1 parent 076ef29 commit d522c14
Show file tree
Hide file tree
Showing 16 changed files with 359 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,9 @@ Resources:
<%if (props.authProviders.indexOf('www.amazon.com') !== -1) { %>
www.amazon.com: !Ref amazonAppId
<% } %>
<%if (props.authProviders.indexOf('appleid.apple.com') !== -1) { %>
appleid.apple.com: !Ref appleAppId
<% } %>
<% } %>
AllowUnauthenticatedIdentities: !Ref allowUnauthenticatedIdentities
<%if (props.audiences && props.audiences.length > 0) { %>
Expand Down Expand Up @@ -1205,4 +1208,8 @@ Outputs :
AmazonWebClient:
Value: !Ref amazonAppId
<% } %>
<%if (props.appleAppId) { %>
AppleWebClient:
Value: !Ref appleAppId
<% } %>
<% } %>
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,11 @@ const authProviders = [
value: 'www.amazon.com',
answerHashKey: 'amazonAppId',
},
{
name: 'Apple',
value: 'appleid.apple.com',
answerHashKey: 'appleAppId',
},
];

const hostedUIProviders = [
Expand All @@ -434,6 +439,10 @@ const hostedUIProviders = [
name: 'Login With Amazon',
value: 'LoginWithAmazon',
},
{
name: 'Sign in with Apple',
value: 'SignInWithApple',
},
];

const authorizeScopes = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ export const ENV_SPECIFIC_PARAMS = [
'amazonAppId',
'loginwithamazonAppIdUserPool',
'loginwithamazonAppSecretUserPool',
'signinwithappleClientIdUserPool',
'signinwithappleTeamIdUserPool',
'signinwithappleKeyIdUserPool',
'signinwithapplePrivateKeyUserPool',
'hostedUIProviderCreds',
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { importMessages } from './messages';
import uuid from 'uuid';

// Currently the CLI only supports the output generation of these providers
const supportedIdentityProviders = ['COGNITO', 'Facebook', 'Google', 'LoginWithAmazon'];
const supportedIdentityProviders = ['COGNITO', 'Facebook', 'Google', 'LoginWithAmazon', 'SignInWithApple'];

export const importResource = async (
context: $TSContext,
Expand Down Expand Up @@ -752,6 +752,9 @@ const createMetaOutput = (answers: ImportAnswers, hasOAuthConfig: boolean): Meta
case 'accounts.google.com':
output.GoogleWebClient = answers.identityPool!.SupportedLoginProviders![key];
break;
case 'appleid.apple.com':
output.AppleWebClient = answers.identityPool!.SupportedLoginProviders![key];
break;
default:
// We don't do anything with the providers that the CLI currently does not support.
break;
Expand Down Expand Up @@ -815,6 +818,9 @@ const createEnvSpecificResourceParameters = (
case 'graph.facebook.com':
envSpecificResourceParameters.facebookAppId = answers.identityPool!.SupportedLoginProviders![key];
break;
case 'appleid.apple.com':
envSpecificResourceParameters.appleAppId = answers.identityPool!.SupportedLoginProviders![key];
break;
case 'accounts.google.com': {
switch (projectType) {
case 'javascript':
Expand All @@ -840,11 +846,23 @@ const createEnvSpecificResourceParameters = (
};

const createOAuthCredentials = (identityProviders: IdentityProviderType[]): string => {
const credentials = identityProviders.map(idp => ({
ProviderName: idp.ProviderName!,
client_id: idp.ProviderDetails!.client_id,
client_secret: idp.ProviderDetails!.client_secret,
}));
const credentials = identityProviders.map(idp => {
if (idp.ProviderName === 'SignInWithApple') {
return {
ProviderName: idp.ProviderName!,
client_id: idp.ProviderDetails!.client_id,
team_id: idp.ProviderDetails!.team_id,
key_id: idp.ProviderDetails!.key_id,
private_key: idp.ProviderDetails!.private_key,
};
} else {
return {
ProviderName: idp.ProviderName!,
client_id: idp.ProviderDetails!.client_id,
client_secret: idp.ProviderDetails!.client_secret,
};
}
});

return JSON.stringify(credentials);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export type MetaOutput = {
AmazonWebClient?: string;
FacebookWebClient?: string;
GoogleWebClient?: string;
AppleWebClient?: string;
HostedUIDomain?: string;
OAuthMetadata?: string;
CreatedSNSRole?: string;
Expand All @@ -59,6 +60,7 @@ export type EnvSpecificResourceParameters = {
identityPoolName?: string;
facebookAppId?: string;
amazonAppId?: string;
appleAppId?: string;
googleIos?: string;
googleAndroid?: string;
googleClientId?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,15 @@ function getOAuthProviderKeys(currentEnvSpecificValues, resourceParams) {
const configuredProviders = JSON.parse(hostedUIProviderCreds).map(h => h.ProviderName);
const deltaProviders = _.intersection(oAuthProviders, configuredProviders);
deltaProviders.forEach(d => {
currentEnvSpecificValues[`${d.toLowerCase()}AppIdUserPool`] = configuredProviders[`${d.toLowerCase()}AppIdUserPool`];
currentEnvSpecificValues[`${d.toLowerCase()}AppSecretUserPool`] = configuredProviders[`${d.toLowerCase()}AppSecretUserPool`];
if (d === 'SignInWithApple') {
currentEnvSpecificValues[`${d.toLowerCase()}ClientIdUserPool`] = configuredProviders[`${d.toLowerCase()}ClientIdUserPool`];
currentEnvSpecificValues[`${d.toLowerCase()}TeamIdUserPool`] = configuredProviders[`${d.toLowerCase()}TeamIdUserPool`];
currentEnvSpecificValues[`${d.toLowerCase()}KeyIdUserPool`] = configuredProviders[`${d.toLowerCase()}KeyIdUserPool`];
currentEnvSpecificValues[`${d.toLowerCase()}PrivateKeyUserPool`] = configuredProviders[`${d.toLowerCase()}PrivateKeyUserPool`];
} else {
currentEnvSpecificValues[`${d.toLowerCase()}AppIdUserPool`] = configuredProviders[`${d.toLowerCase()}AppIdUserPool`];
currentEnvSpecificValues[`${d.toLowerCase()}AppSecretUserPool`] = configuredProviders[`${d.toLowerCase()}AppSecretUserPool`];
}
});
return currentEnvSpecificValues;
}
Expand Down Expand Up @@ -249,15 +256,34 @@ function formatCredsforEnvParams(currentEnvSpecificValues, result, resourceParam
function parseCredsForHeadless(mergedValues, envParams) {
const oAuthProviders = JSON.parse(mergedValues.hostedUIProviderMeta).map(h => h.ProviderName);
envParams.hostedUIProviderCreds = JSON.stringify(
oAuthProviders.map(el => ({
ProviderName: el,
client_id: mergedValues[`${el.toLowerCase()}AppIdUserPool`],
client_secret: mergedValues[`${el.toLowerCase()}AppSecretUserPool`],
})),
oAuthProviders.map(el => {
if (el === 'SignInWithApple') {
return {
ProviderName: el,
client_id: mergedValues[`${el.toLowerCase()}ClientIdUserPool`],
team_id: mergedValues[`${el.toLowerCase()}TeamIdUserPool`],
key_id: mergedValues[`${el.toLowerCase()}KeyIdUserPool`],
private_key: mergedValues[`${el.toLowerCase()}PrivateKeyUserPool`],
};
} else {
return {
ProviderName: el,
client_id: mergedValues[`${el.toLowerCase()}AppIdUserPool`],
client_secret: mergedValues[`${el.toLowerCase()}AppSecretUserPool`],
};
}
}),
);
oAuthProviders.forEach(i => {
delete envParams[`${i.toLowerCase()}AppIdUserPool`];
delete envParams[`${i.toLowerCase()}AppSecretUserPool`];
if (i === 'SignInWithApple') {
delete envParams[`${i.toLowerCase()}ClientIdUserPool`];
delete envParams[`${i.toLowerCase()}TeamIdUserPool`];
delete envParams[`${i.toLowerCase()}KeyIdUserPool`];
delete envParams[`${i.toLowerCase()}PrivateKeyUserPool`];
} else {
delete envParams[`${i.toLowerCase()}AppIdUserPool`];
delete envParams[`${i.toLowerCase()}AppSecretUserPool`];
}
});
}

Expand All @@ -280,14 +306,24 @@ function getRequiredParamsForHeadlessInit(projectType, previousValues) {
if (previousValues.authProviders.includes('www.amazon.com')) {
requiredParams.push('amazonAppId');
}
if (previousValues.authProviders.includes('appleid.apple.com')) {
requiredParams.push('appleAppId');
}
}

if (previousValues.hostedUIProviderMeta) {
const oAuthProviders = JSON.parse(previousValues.hostedUIProviderMeta).map(h => h.ProviderName);
if (oAuthProviders && oAuthProviders.length > 0) {
oAuthProviders.forEach(o => {
requiredParams.push(`${o.toLowerCase()}AppIdUserPool`);
requiredParams.push(`${o.toLowerCase()}AppSecretUserPool`);
if (o === 'SignInWithApple') {
requiredParams.push(`${o.toLowerCase()}ClientIdUserPool`);
requiredParams.push(`${o.toLowerCase()}TeamIdUserPool`);
requiredParams.push(`${o.toLowerCase()}KeyIdUserPool`);
requiredParams.push(`${o.toLowerCase()}PrivateKeyUserPool`);
} else {
requiredParams.push(`${o.toLowerCase()}AppIdUserPool`);
requiredParams.push(`${o.toLowerCase()}AppSecretUserPool`);
}
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -530,8 +530,15 @@ function parseOAuthCreds(providers, metadata, envCreds) {
try {
const provider = parsedMetaData.find(i => i.ProviderName === el);
const creds = parsedCreds.find(i => i.ProviderName === el);
providerKeys[`${el.toLowerCase()}AppIdUserPool`] = creds.client_id;
providerKeys[`${el.toLowerCase()}AppSecretUserPool`] = creds.client_secret;
if (el === 'SignInWithApple') {
providerKeys[`${el.toLowerCase()}ClientIdUserPool`] = creds.client_id;
providerKeys[`${el.toLowerCase()}TeamIdUserPool`] = creds.team_id;
providerKeys[`${el.toLowerCase()}KeyIdUserPool`] = creds.key_id;
providerKeys[`${el.toLowerCase()}PrivateKeyUserPool`] = creds.private_key;
} else {
providerKeys[`${el.toLowerCase()}AppIdUserPool`] = creds.client_id;
providerKeys[`${el.toLowerCase()}AppSecretUserPool`] = creds.client_secret;
}
providerKeys[`${el.toLowerCase()}AuthorizeScopes`] = provider.authorize_scopes.split(',');
} catch (e) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,20 @@ export const supportedServices = {
},
],
},
{
key: 'appleAppId',
prefix:
" \n You've opted to allow users to authenticate via Apple. If you haven't already, you'll need to go to https://developer.apple.com/programs/enroll/ and create an App ID. \n",
question: 'Enter your Apple App ID for your identity pool: ',
required: true,
andConditions: [
{
key: 'authProviders',
value: 'appleid.apple.com',
operator: 'includes',
},
],
},
{
key: 'userPoolName',
question: 'Please provide a name for your user pool:',
Expand Down Expand Up @@ -308,7 +322,8 @@ export const supportedServices = {
{
key: 'adminQueries',
question: 'Do you want to add an admin queries API?',
learnMore: 'Admin Queries API let you perform user admin functions from your frontend. See https://docs.amplify.aws/cli/auth/admin#admin-queries-api for more.',
learnMore:
'Admin Queries API let you perform user admin functions from your frontend. See https://docs.amplify.aws/cli/auth/admin#admin-queries-api for more.',
required: true,
type: 'list',
map: 'booleanOptions',
Expand Down Expand Up @@ -733,7 +748,7 @@ export const supportedServices = {
key: 'hostedUI',
question: 'Do you want to use an OAuth flow?',
learnMore:
'When you create a user pool in Amazon Cognito and configure a domain for it, Amazon Cognito automatically provisions a hosted web UI to let you add sign-up and sign-in pages to your app. Selecting "No" will remove any existing OAuth configuration.',
'When you create a user pool in Amazon Cognito and configure a domain for it, Amazon Cognito automatically provisions a hosted web UI to let you add sign-up and sign-in pages to your app. Selecting "No" will remove any existing OAuth configuration.',
required: true,
type: 'list',
map: 'booleanOptions',
Expand Down Expand Up @@ -1164,6 +1179,56 @@ export const supportedServices = {
},
],
},
{
key: 'signinwithappleClientIdUserPool',
prefix:
" \n You've opted to allow users to authenticate via Apple. If you haven't already, you'll need to create an Amazon App ID. Head to https://developer.apple.com/programs/enroll to learn more. \n",
question: 'Enter your Sign in with Apple Client ID for your OAuth flow: ',
required: true,
andConditions: [
{
key: 'authProvidersUserPool',
value: 'SignInWithApple',
operator: 'includes',
},
],
},
{
key: 'signinwithappleTeamIdUserPool',
question: 'Enter your Sign in with Apple Team ID for your OAuth flow: ',
required: true,
andConditions: [
{
key: 'authProvidersUserPool',
value: 'SignInWithApple',
operator: 'includes',
},
],
},
{
key: 'signinwithappleKeyIdUserPool',
question: 'Enter your Sign in with Apple Key ID for your OAuth flow: ',
required: true,
andConditions: [
{
key: 'authProvidersUserPool',
value: 'SignInWithApple',
operator: 'includes',
},
],
},
{
key: 'signinwithapplePrivateKeyUserPool',
question: 'Enter your Sign in with Apple Private Key for your OAuth flow: ',
required: true,
andConditions: [
{
key: 'authProvidersUserPool',
value: 'SignInWithApple',
operator: 'includes',
},
],
},
],
cfnFilename: 'auth-template.yml.ejs',
defaultValuesFilename: 'cognito-defaults.js',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@ describe('amplify app console tests', () => {
GOOGLE_APP_SECRET,
AMAZON_APP_ID,
AMAZON_APP_SECRET,
APPLE_APP_ID,
APPLE_TEAM_ID,
APPLE_KEY_ID,
APPLE_PRIVATE_KEY,
} = getSocialProviders();
await initJSProjectWithProfile(projRoot, { disableAmplifyAppCreation: false, name: 'authConsoleTest', envName });
await addAuthWithDefaultSocial(projRoot, {});
Expand Down Expand Up @@ -226,6 +230,10 @@ describe('amplify app console tests', () => {
googleAppSecretUserPool: GOOGLE_APP_SECRET,
loginwithamazonAppIdUserPool: AMAZON_APP_ID,
loginwithamazonAppSecretUserPool: AMAZON_APP_SECRET,
signinwithappleClientIdUserPool: APPLE_APP_ID,
signinwithappleTeamIdUserPool: APPLE_TEAM_ID,
signinwithappleKeyIdUserPool: APPLE_KEY_ID,
signinwithapplePrivateKeyUserPool: APPLE_PRIVATE_KEY,
},
});

Expand All @@ -251,6 +259,10 @@ describe('amplify app console tests', () => {
googleAppSecretUserPool: GOOGLE_APP_SECRET,
loginwithamazonAppIdUserPool: AMAZON_APP_ID,
loginwithamazonAppSecretUserPool: AMAZON_APP_SECRET,
signinwithappleClientIdUserPool: APPLE_APP_ID,
signinwithappleTeamIdUserPool: APPLE_TEAM_ID,
signinwithappleKeyIdUserPool: APPLE_KEY_ID,
signinwithapplePrivateKeyUserPool: APPLE_PRIVATE_KEY,
},
},
{
Expand Down
Loading

0 comments on commit d522c14

Please sign in to comment.