Skip to content

Commit

Permalink
feat(cognito): user pool identity support for Google (#10649)
Browse files Browse the repository at this point in the history
Added support for Google  in cognito user pool identity.

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
asjadsaboor-10p authored Oct 15, 2020
1 parent 5f164af commit 49ede22
Show file tree
Hide file tree
Showing 14 changed files with 361 additions and 26 deletions.
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-cognito/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ The following third-party identity providers are currentlhy supported in the CDK

* [Login With Amazon](https://developer.amazon.com/apps-and-games/login-with-amazon)
* [Facebook Login](https://developers.facebook.com/docs/facebook-login/)
* [Google Login](https://developers.google.com/identity/sign-in/web/sign-in)

The following code configures a user pool to federate with the third party provider, 'Login with Amazon'. The identity
provider needs to be configured with a set of credentials that the Cognito backend can use to federate with the
Expand Down
6 changes: 6 additions & 0 deletions packages/@aws-cdk/aws-cognito/lib/user-pool-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,12 @@ export class UserPoolClientIdentityProvider {
*/
public static readonly FACEBOOK = new UserPoolClientIdentityProvider('Facebook');

/**
* Allow users to sign in using 'Google Login'.
* A `UserPoolIdentityProviderGoogle` must be attached to the user pool.
*/
public static readonly GOOGLE = new UserPoolClientIdentityProvider('Google');

/**
* Allow users to sign in using 'Login With Amazon'.
* A `UserPoolIdentityProviderAmazon` must be attached to the user pool.
Expand Down
19 changes: 19 additions & 0 deletions packages/@aws-cdk/aws-cognito/lib/user-pool-idps/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,25 @@ export class ProviderAttribute {
/** The locale attribute provided by Facebook */
public static readonly FACEBOOK_LOCALE = new ProviderAttribute('locale');

/** The name attribute provided by Google */
public static readonly GOOGLE_NAMES = new ProviderAttribute('names');
/** The gender attribute provided by Google */
public static readonly GOOGLE_GENDER = new ProviderAttribute('gender');
/** The birthday attribute provided by Google */
public static readonly GOOGLE_BIRTHDAYS = new ProviderAttribute('birthdays');
/** The birthday attribute provided by Google */
public static readonly GOOGLE_PHONE_NUMBERS = new ProviderAttribute('phoneNumbers');
/** The email attribute provided by Google */
public static readonly GOOGLE_EMAIL = new ProviderAttribute('email');
/** The name attribute provided by Google */
public static readonly GOOGLE_NAME = new ProviderAttribute('name');
/** The email attribute provided by Google */
public static readonly GOOGLE_PICTURE = new ProviderAttribute('picture');
/** The email attribute provided by Google */
public static readonly GOOGLE_GIVEN_NAME = new ProviderAttribute('given_name');
/** The email attribute provided by Google */
public static readonly GOOGLE_FAMILY_NAME = new ProviderAttribute('family_name');

/**
* Use this to specify an attribute from the identity provider that is not pre-defined in the CDK.
* @param attributeName the attribute value string as recognized by the provider
Expand Down
53 changes: 53 additions & 0 deletions packages/@aws-cdk/aws-cognito/lib/user-pool-idps/google.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Construct } from 'constructs';
import { CfnUserPoolIdentityProvider } from '../cognito.generated';
import { UserPoolIdentityProviderBase, UserPoolIdentityProviderProps } from './base';

/**
* Properties to initialize UserPoolGoogleIdentityProvider
*/
export interface UserPoolIdentityProviderGoogleProps extends UserPoolIdentityProviderProps {
/**
* The client id recognized by Google APIs.
* @see https://developers.google.com/identity/sign-in/web/sign-in#specify_your_apps_client_id
*/
readonly clientId: string;
/**
* The client secret to be accompanied with clientId for Google APIs to authenticate the client.
* @see https://developers.google.com/identity/sign-in/web/sign-in
*/
readonly clientSecret: string;
/**
* The list of google permissions to obtain for getting access to the google profile
* @see https://developers.google.com/identity/sign-in/web/sign-in
* @default [ profile ]
*/
readonly scopes?: string[];
}

/**
* Represents a identity provider that integrates with 'Google'
* @resource AWS::Cognito::UserPoolIdentityProvider
*/
export class UserPoolIdentityProviderGoogle extends UserPoolIdentityProviderBase {
public readonly providerName: string;

constructor(scope: Construct, id: string, props: UserPoolIdentityProviderGoogleProps) {
super(scope, id, props);

const scopes = props.scopes ?? ['profile'];

const resource = new CfnUserPoolIdentityProvider(this, 'Resource', {
userPoolId: props.userPool.userPoolId,
providerName: 'Google', // must be 'Google' when the type is 'Google'
providerType: 'Google',
providerDetails: {
client_id: props.clientId,
client_secret: props.clientSecret,
authorize_scopes: scopes.join(' '),
},
attributeMapping: super.configureAttributeMapping(),
});

this.providerName = super.getResourceNameAttribute(resource.ref);
}
}
3 changes: 2 additions & 1 deletion packages/@aws-cdk/aws-cognito/lib/user-pool-idps/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './base';
export * from './amazon';
export * from './facebook';
export * from './facebook';
export * from './google';
3 changes: 2 additions & 1 deletion packages/@aws-cdk/aws-cognito/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@
"resource-attribute:@aws-cdk/aws-cognito.UserPoolClient.userPoolClientClientSecret",
"props-physical-name:@aws-cdk/aws-cognito.UserPoolDomainProps",
"props-physical-name:@aws-cdk/aws-cognito.UserPoolIdentityProviderFacebookProps",
"props-physical-name:@aws-cdk/aws-cognito.UserPoolIdentityProviderAmazonProps"
"props-physical-name:@aws-cdk/aws-cognito.UserPoolIdentityProviderAmazonProps",
"props-physical-name:@aws-cdk/aws-cognito.UserPoolIdentityProviderGoogleProps"
]
},
"stability": "experimental",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -680,10 +680,16 @@
"myuserpool01998219": {
"Type": "AWS::Cognito::UserPool",
"Properties": {
"AccountRecoverySetting": {
"AccountRecoverySetting": {
"RecoveryMechanisms": [
{ "Name": "verified_phone_number", "Priority": 1 },
{ "Name": "verified_email", "Priority": 2 }
{
"Name": "verified_phone_number",
"Priority": 1
},
{
"Name": "verified_email",
"Priority": 2
}
]
},
"AdminCreateUserConfig": {
Expand All @@ -701,16 +707,8 @@
"email",
"phone_number"
],
"EmailConfiguration": {
"From": "[email protected]",
"ReplyToEmailAddress": "[email protected]"
},
"EmailVerificationMessage": "verification email body from the integ test. Code is {####}.",
"EmailVerificationSubject": "verification email subject from the integ test",
"EnabledMfas": [
"SMS_MFA",
"SOFTWARE_TOKEN_MFA"
],
"LambdaConfig": {
"CreateAuthChallenge": {
"Fn::GetAtt": [
Expand Down Expand Up @@ -773,7 +771,7 @@
]
}
},
"MfaConfiguration": "ON",
"MfaConfiguration": "OFF",
"Policies": {
"PasswordPolicy": {
"MinimumLength": 12,
Expand All @@ -786,14 +784,14 @@
},
"Schema": [
{
"Mutable": true,
"Name": "name",
"Required": true,
"Mutable": true
"Required": true
},
{
"Mutable": true,
"Name": "email",
"Required": true,
"Mutable": true
"Required": true
},
{
"AttributeDataType": "String",
Expand Down Expand Up @@ -881,4 +879,4 @@
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const userpool = new UserPool(stack, 'myuserpool', {
'some-boolean-attr': new BooleanAttribute(),
'some-datetime-attr': new DateTimeAttribute(),
},
mfa: Mfa.REQUIRED,
mfa: Mfa.OFF,
mfaSecondFactor: {
sms: true,
otp: true,
Expand All @@ -56,10 +56,6 @@ const userpool = new UserPool(stack, 'myuserpool', {
requireUppercase: true,
requireSymbols: true,
},
emailSettings: {
from: '[email protected]',
replyTo: '[email protected]',
},
lambdaTriggers: {
createAuthChallenge: dummyTrigger('createAuthChallenge'),
customMessage: dummyTrigger('customMessage'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ProviderAttribute, UserPool, UserPoolIdentityProviderAmazon } from '../
* * If you plug in valid 'Login with Amazon' credentials, the federated log in should work.
*/
const app = new App();
const stack = new Stack(app, 'integ-user-pool-idp');
const stack = new Stack(app, 'integ-user-pool-idp-amazon');

const userpool = new UserPool(stack, 'pool');

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
{
"Resources": {
"pool056F3F7E": {
"Type": "AWS::Cognito::UserPool",
"Properties": {
"AccountRecoverySetting": {
"RecoveryMechanisms": [
{
"Name": "verified_phone_number",
"Priority": 1
},
{
"Name": "verified_email",
"Priority": 2
}
]
},
"AdminCreateUserConfig": {
"AllowAdminCreateUserOnly": true
},
"EmailVerificationMessage": "The verification code to your new account is {####}",
"EmailVerificationSubject": "Verify your new account",
"SmsVerificationMessage": "The verification code to your new account is {####}",
"VerificationMessageTemplate": {
"DefaultEmailOption": "CONFIRM_WITH_CODE",
"EmailMessage": "The verification code to your new account is {####}",
"EmailSubject": "Verify your new account",
"SmsMessage": "The verification code to your new account is {####}"
}
}
},
"poolclient2623294C": {
"Type": "AWS::Cognito::UserPoolClient",
"Properties": {
"UserPoolId": {
"Ref": "pool056F3F7E"
},
"AllowedOAuthFlows": [
"implicit",
"code"
],
"AllowedOAuthFlowsUserPoolClient": true,
"AllowedOAuthScopes": [
"profile",
"phone",
"email",
"openid",
"aws.cognito.signin.user.admin"
],
"CallbackURLs": [
"https://example.com"
],
"SupportedIdentityProviders": [
{
"Ref": "googleDB2C5242"
},
"COGNITO"
]
}
},
"pooldomain430FA744": {
"Type": "AWS::Cognito::UserPoolDomain",
"Properties": {
"Domain": "nija-test-pool",
"UserPoolId": {
"Ref": "pool056F3F7E"
}
}
},
"googleDB2C5242": {
"Type": "AWS::Cognito::UserPoolIdentityProvider",
"Properties": {
"ProviderName": "Google",
"ProviderType": "Google",
"UserPoolId": {
"Ref": "pool056F3F7E"
},
"AttributeMapping": {
"given_name": "given_name",
"family_name": "family_name",
"email": "email",
"gender": "gender",
"names": "names"
},
"ProviderDetails": {
"client_id": "google-client-id",
"client_secret": "google-client-secret",
"authorize_scopes": "profile"
}
}
}
},
"Outputs": {
"SignInLink": {
"Value": {
"Fn::Join": [
"",
[
"https://",
{
"Ref": "pooldomain430FA744"
},
".auth.",
{
"Ref": "AWS::Region"
},
".amazoncognito.com/login?client_id=",
{
"Ref": "poolclient2623294C"
},
"&response_type=code&redirect_uri=https://example.com"
]
]
}
}
}
}
41 changes: 41 additions & 0 deletions packages/@aws-cdk/aws-cognito/test/integ.user-pool-idp.google.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { App, CfnOutput, Stack } from '@aws-cdk/core';
import { ProviderAttribute, UserPool, UserPoolIdentityProviderGoogle } from '../lib';

/*
* Stack verification steps
* * Visit the URL provided by stack output 'SignInLink' in a browser, and verify the 'Google' sign in link shows up.
* * If you plug in valid 'Google' credentials, the federated log in should work.
*/
const app = new App();
const stack = new Stack(app, 'integ-user-pool-idp-google');

const userpool = new UserPool(stack, 'pool');

new UserPoolIdentityProviderGoogle(stack, 'google', {
userPool: userpool,
clientId: 'google-client-id',
clientSecret: 'google-client-secret',
attributeMapping: {
givenName: ProviderAttribute.GOOGLE_GIVEN_NAME,
familyName: ProviderAttribute.GOOGLE_FAMILY_NAME,
email: ProviderAttribute.GOOGLE_EMAIL,
gender: ProviderAttribute.GOOGLE_GENDER,
custom: {
names: ProviderAttribute.GOOGLE_NAMES,
},
},
});

const client = userpool.addClient('client');

const domain = userpool.addDomain('domain', {
cognitoDomain: {
domainPrefix: 'nija-test-pool',
},
});

new CfnOutput(stack, 'SignInLink', {
value: domain.signInUrl(client, {
redirectUri: 'https://example.com',
}),
});
3 changes: 2 additions & 1 deletion packages/@aws-cdk/aws-cognito/test/user-pool-client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -451,13 +451,14 @@ describe('User Pool Client', () => {
UserPoolClientIdentityProvider.COGNITO,
UserPoolClientIdentityProvider.FACEBOOK,
UserPoolClientIdentityProvider.AMAZON,
UserPoolClientIdentityProvider.GOOGLE,
],
});

// THEN
expect(stack).toHaveResource('AWS::Cognito::UserPoolClient', {
ClientName: 'AllEnabled',
SupportedIdentityProviders: ['COGNITO', 'Facebook', 'LoginWithAmazon'],
SupportedIdentityProviders: ['COGNITO', 'Facebook', 'LoginWithAmazon', 'Google'],
});
});

Expand Down
Loading

0 comments on commit 49ede22

Please sign in to comment.