4

I have a Cognito User Pool configured to give access to and API Gateway, and it's working nicely. I use the hosted UI for a user to log in, and they got a token_id which grants them access to the API. The trouble is, this is meant to be restricted, and currently anyone can sign up via Google as an identity provider.

The end goal is to have company users sign in with google to keep things simple for them. These users should be created by an admin first, then they log in.

I have this option configured: Cognito User Pool Policies

And yet, just anyone can login via google and a user is created for them. This seems to be in direct contradiction to this setting.

Any thoughts are welcome!

counterbeing
  • 2,721
  • 2
  • 27
  • 47

2 Answers2

2

I had a similar requirement. First, the admin must create an account for john.deo@abc.com and jenny.deo@xyz.com (assume these are company users and both abc.com and xyz.com are having Google email accounts). A Cognito profile will be created for them. When they sign in with their Google account, Cognito by default creates another account for them. So in the Cognito user pool, there will be 4 accounts in total.

To prevent this I was using the "Pre sign-up" trigger as suggested here. But still, it was allowing any user with a Google account to Sign In. So I modified the code as following if there is no Cognito profile created already the user will be redirected back to the login screen with an error.

import json
import boto3

client = boto3.client('cognito-idp')


def lambda_handler(event, context):
    print("Event: ", event)
    email = event['request']['userAttributes']['email']

    # Find a user with the same email
    response = client.list_users(
        UserPoolId=event['userPoolId'],
        AttributesToGet=[
            'email',
        ],
        Filter='email = "{}"'.format(email)
    )

    if not hasattr(response, 'Users'):
        return "You cannot Sign Up with this email";
    
    print('Users found: ', response['Users'])

    for user in response['Users']:
        provider = None
        provider_value = None
        # Check which provider it is using
        if event['userName'].startswith('google_'):
            provider = 'Google'
            provider_value = event['userName'].split('_')[1]

        print('Linking accounts from Email {} with provider {}: '.format(
            email,
            provider
        ))

        # If the signup is coming from a social provider, link the accounts
        # with admin_link_provider_for_user function
        if provider and provider_value:
            print('> Linking user: ', user)
            print('> Provider Id: ', provider_value)
            response = client.admin_link_provider_for_user(
                UserPoolId=event['userPoolId'],
                DestinationUser={
                    'ProviderName': 'Cognito',
                    'ProviderAttributeValue': user['Username']
                },
                SourceUser={
                    'ProviderName': provider,
                    'ProviderAttributeName': 'Cognito_Subject',
                    'ProviderAttributeValue': provider_value
                }
            )
    # Return the event to continue the workflow
    return event
1

By configuring Google as an identity provider in Cognito, you are essentially saying anyone with a Google account can sign into my application (what they can do is up to you). You don't have to then create user identities for them in Cognito, they already have them in Google. The option you have shown above essentially disables the SignUp API action in Cognito, so no one would be allowed to self register themselves in your User Pool. But if they have a Google account, you've already given them permission to log in.

If you want to lock it down to your company identities, you need to use another method like SAML authentication. If you're using GSuite, this is the route you should use as GSuite is then your corporate directory, not the same thing as a Google Account

S.B.G
  • 290
  • 3
  • 16