Use Amazon Cognito as Identity Provider
In this article, you will learn the basic setup of Amazon Cognito as an Identity Provider for GoodData. In order to keep this example reproducible and universal, the commands below are written in Bash shell and use AWS CLI version 2. If you use a different deployment tool (like CloudFormation or Terraform), or if you decide to configure your Amazon Congito manually using AWS Console, you’ll need to adapt these scipts.
Set up shared environment
Set the following environment variables in the shell you will later use for running the aws-cli commands. Adjust values according to your conditions.
VARIABLE | Example value | Explanation |
---|---|---|
AWS_REGION | eu-central-1 | AWS region where Cognito will be deployed |
ORG_HOSTNAME | example.gooddata.com | Hostname of GoodData organization |
ORGANIZATION_ID | alpha | Organization ID |
API_TOKEN | YWRtaW46Ym9vdHN0cmFwOmRlbW8xMjM= | Token with MANAGE permission on your Organization |
ORG_PORT | "" | Set to port number if it differs from 80 or 443 |
ORG_SCHEMA | https | Organization URL schema, http or https |
export AWS_REGION="eu-central-1"
export ORG_HOSTNAME="example.gooddata.com"
export ORGANIZATION_ID="alpha"
export API_TOKEN="YWRtaW46Ym9vdHN0cmFwOmRlbW8xMjM="
export ORG_PORT=""
export ORG_SCHEMA="https"
export HOST_URL="${ORG_SCHEMA}://${ORG_HOSTNAME}${ORG_PORT:+:$ORG_PORT}"
User pool configuration
Create Cognito user pool
The following command creates AWS Cognito User pool. It will
be called gdcn-demo
and will use simple password policy:
- minimum 8 characters
- must use upper case, lower case, and numeric characters
- assigned temporary password will be valid for 7 days
To make this example simple, new accounts will have their e-mail addresses set as verified, multi-factor authentication will be turned off and e-mail communication will be sent from aws-provided account.
More importantly, name
user attribute is set as required to
make sure it is always present for every user. This attribute
will be retrieved from user id token by GoodData to get
information about user that just logged in.
The resulting id of created user pool will be stored in
environment variable USERPOOL_ID
that will be used later.
USERPOOL_ID=$( \
aws cognito-idp create-user-pool --pool-name gdcn-demo \
--policies 'PasswordPolicy={MinimumLength=8,RequireUppercase=true,RequireLowercase=true,RequireNumbers=true,RequireSymbols=false,TemporaryPasswordValidityDays=7}' \
--auto-verified-attributes email --alias-attributes email \
--verification-message-template 'DefaultEmailOption=CONFIRM_WITH_CODE' \
--mfa-configuration OFF --user-attribute-update-settings \
'AttributesRequireVerificationBeforeUpdate=email' \
--schema \
Name=name,AttributeDataType=String,Mutable=true,Required=true \
Name=email,AttributeDataType=String,Mutable=true,Required=true \
--email-configuration 'EmailSendingAccount=COGNITO_DEFAULT' \
--admin-create-user-config 'AllowAdminCreateUserOnly=true' \
--username-configuration 'CaseSensitive=False' \
--account-recovery-setting 'RecoveryMechanisms=[{Priority=1,Name=verified_email}]' \
--query 'UserPool.Id' --output text)
echo "Created User Pool '$USERPOOL_ID'"
Create Cognito domain
Cognito needs a domain where login form UI elements and OAuth2
service will be hosted. We will use AWS-hosted domain. The
resulting URL will be https://<<domain>>.auth.<<region>>.amazoncognito.com/
. It is also possible to use custom domain, like https://auth.gooddata.com/
. Refer to AWS documentation for details.
This command will create domain https://gdcn-demo.auth.eu-central-1.amazoncognito.com/
:
aws cognito-idp create-user-pool-domain \
--user-pool-id "${USERPOOL_ID}" --domain gdcn-demo
Create cognito user pool client
In order to use this user pool as a source of truth for user authententication, we need to create OAuth 2.0 client. This command will make such client that will be later configured in GoodData Organization.
read -a POOL_CLIENT < <(aws cognito-idp create-user-pool-client \
--user-pool-id "$USERPOOL_ID" --client-name gdcn-client --generate-secret \
--supported-identity-providers COGNITO \
--callback-urls "$HOST_URL/login/oauth2/code/$ORG_HOSTNAME" \
--allowed-o-auth-flows-user-pool-client \
--allowed-o-auth-scopes email openid profile --allowed-o-auth-flows code \
--query 'UserPoolClient.[ClientSecret, ClientId]' --output text)
echo "Created Client with id='${POOL_CLIENT[1]}' and secret='${POOL_CLIENT[0]}'"
Variable ${POOL_CLIENT[0]}
contains client secret and ${POOL_CLIENT[1]}
contains
client id.
Configure Cognito IdP in Organization
Update GoodData organization with OAuth 2.0 client you just created. You will need to prepare API request payload containing information retrieved in previous steps:
oauthClientId
- ID of OAuth 2.0 client, stored in${POOL_CLIENT[1]}
variableoauthClientSecret
- client secret, stored in${POOL_CLIENT[0]}
variableoauthIssuerLocation
- URL of oauth issuer. For Cognito, it has always formathttps://cognito-idp.<<aws-region>>.amazonaws.com/<<user-pool-id>>
# prepare request payload
read -r -d '' PAYLOAD <<EOF
{
"data": {
"id": "$ORGANIZATION_ID",
"type": "organization",
"attributes": {
"name": "Cognito Auth Demo",
"hostname": "$ORG_HOSTNAME",
"oauthIssuerLocation": "https://cognito-idp.$AWS_REGION.amazonaws.com/$USERPOOL_ID",
"oauthClientId": "${POOL_CLIENT[1]}",
"oauthClientSecret": "${POOL_CLIENT[0]}"
}
}
}
EOF
# Update organization
curl -X PUT -H "Authorization: Bearer $API_TOKEN" \
-H 'Content-Type: application/vnd.gooddata.api+json' -d "$PAYLOAD" \
$HOST_URL/api/v1/entities/admin/organizations/$ORGANIZATION_ID
Provision user to user pool
There are multiple ways how to add users into Cognito user pool.
In this example, we create a new user using admin-create-user
API, it’s also possible to import users from CSV file. Refer to
AWS documentation for further details.
# Set up variables
USER_EMAIL="john.doe@example.com"
USER_NAME="John Doe"
USER_LOGIN="john.doe"
# Note the password must conform to user pool password policy
USER_PASSWORD="NewRandomPa33word"
# Create first user
EXTERNAL_ID=$( \
aws cognito-idp admin-create-user --user-pool-id $USERPOOL_ID \
--username "$USER_LOGIN" --user-attributes Name=email,Value="$USER_EMAIL" \
Name=email_verified,Value=True Name=name,Value="$USER_NAME" \
--temporary-password "$USER_PASSWORD" --message-action SUPPRESS \
--desired-delivery-mediums EMAIL --output text \
--query 'User.Attributes[?Name==`sub`].Value[]')
echo "Created user with login='$USER_LOGIN' and password='$USER_PASSWORD'"
Link Cognito user with GoodData user
# prepare request payload
read -r -d '' PAYLOAD <<EOF
{
"data": {
"id": "$USER_LOGIN",
"type": "user",
"attributes": {
"authenticationId": "$EXTERNAL_ID"
},
"relationships": {
"userGroups": {
"data": [{
"id": "adminGroup",
"type": "userGroup"
}]
}
}
}
}
EOF
# Create user entity
curl -X POST -H "Authorization: Bearer $API_TOKEN" \
-H 'Content-Type: application/vnd.gooddata.api+json' \
-d "$PAYLOAD" $HOST_URL/api/v1/entities/users
# ... or update existing user
curl -X PUT -H "Authorization: Bearer $API_TOKEN" \
-H 'Content-Type: application/vnd.gooddata.api+json' \
-d "$PAYLOAD" $HOST_URL/api/v1/entities/users/$USER_LOGIN
Log in to GoodData
Now you can use web browser to log in to your GoodData
Organization. Just navigate to Organization URL
(https://example.gooddata.com
in previous example) and
enter user login and initial password. On the first login, the
password needs to be changed by user.
Cleanup
When you’re done with test, you may want to delete AWS resources you created. Use these commands to delete user pool domain and user pool itself.
aws cognito-idp delete-user-pool-domain --user-pool-id $USERPOOL_ID --domain gdcn-demo
aws cognito-idp delete-user-pool --user-pool-id $USERPOOL_ID
Known Limitations
RP Initiated Logout does not work at the moment. We plan to implement the functionality in a future release.