AWS Cognito is an Amazon service that authenticates your web and mobile applications, devices, and services. It also allows sign-in through third-party providers such as Facebook, Google, Apple, etc. In addition, AWS Cognito also provides 50K free monthly active users, which is competitive pricing compared to other authentication providers like Auth0, OKTA, etc.
We can also add a custom domain to AWS Cognito to use the OAuth 2.0-compliant authorization server and ready-to-use UI for authentication. The hosted UI included sign-in, sign-up, forgot password, account verification, third-party authentication, and multifactor authentication. Building our OAuth 2.0 authorization is always complex and expensive, but we can use the AWS Cognito-hosted UI for free.
Although AWS Cognito is a secure and production-ready authentication and authorization solution, the hosted UI still has many limitations when customising it to suit our brand. Here are a few of these limitations.
You can try it if you would like to trade off the user experience during sign-up. Otherwise, an AWS Cognito-hosted UI may not be suitable for you.
If you decide to proceed with AWS Cognito, we can create the AWS Cognito with a hosted UI. We will use Terraform to automate the creation of the service. In summary, we need to create a few AWS services using Terraform.
Create a cognito.tf
and paste the following codes.
# Create AWS Cognito User Pool
resource "aws_cognito_user_pool" "main" {
name = "main"
username_attributes = ["email"]
# Use AWS SES to send emails
email_configuration {
email_sending_account = "DEVELOPER"
# TODO: Change this to your email address
from_email_address = "My Website "
# TODO: Change this to your AWS SES domain identity ARN
source_arn = aws_ses_domain_identity.main.arn
}
auto_verified_attributes = ["email"]
user_attribute_update_settings {
attributes_require_verification_before_update = ["email"]
}
# Verify email by sending a link to avoid broken flows of the hosted UI
verification_message_template {
default_email_option = "CONFIRM_WITH_LINK"
}
deletion_protection = "ACTIVE"
}
# Create AWS Cognito User Pool Client
resource "aws_cognito_user_pool_client" "main" {
name = "main"
generate_secret = true
user_pool_id = aws_cognito_user_pool.main.id
allowed_oauth_flows_user_pool_client = true
allowed_oauth_flows = ["code", "implicit"]
allowed_oauth_scopes = ["email", "openid", "phone", "profile"]
supported_identity_providers = ["COGNITO"]
# TODO: Change this to your login callback URL
callback_urls = ["https://mywebsite.com/api/auth/callback/cognito"]
# TODO: Change this to your logout URL
logout_urls = ["https://mywebsite.com"]
}
# Create AWS Cognito User Pool Domain
resource "aws_cognito_user_pool_domain" "main" {
# TODO: Change this to your own domain to host the Cognito UI
domain = "auth.mywebsite.com"
certificate_arn = aws_acm_certificate.main.arn
user_pool_id = aws_cognito_user_pool.main.id
depends_on = [aws_acm_certificate_validation.main]
}
# Create AWS ACM Certificate for the custom domain
resource "aws_acm_certificate" "main" {
# TODO: Change this to your own domain to host the Cognito UI, similar to the domain above
domain_name = "auth.mywebsite.com"
validation_method = "DNS"
lifecycle {
create_before_destroy = true
}
}
# Create Route53 Record for the ACM Certificate verfication
resource "aws_route53_record" "main" {
for_each = {
for dvo in aws_acm_certificate.main.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
}
}
allow_overwrite = true
name = each.value.name
records = [each.value.record]
ttl = 60
type = each.value.type
zone_id = data.aws_route53_zone.main.zone_id
}
# Validate the ACM Certificate
resource "aws_acm_certificate_validation" "main" {
certificate_arn = aws_acm_certificate.main.arn
validation_record_fqdns = [for record in aws_route53_record.main : record.fqdn]
}
# Create Route53 Record for the Cognito User Pool Domain
resource "aws_route53_record" "main_a" {
name = aws_cognito_user_pool_domain.main.domain
type = "A"
zone_id = data.aws_route53_zone.main.zone_id
alias {
evaluate_target_health = false
name = aws_cognito_user_pool_domain.main.cloudfront_distribution
zone_id = aws_cognito_user_pool_domain.main.cloudfront_distribution_zone_id
}
}
You should change all the values that are marked as // TODO
in the code above.
Once you apply all the changes, you should able to access the hosted UI in this URL, and it should be the image below:
https:///oauth2/authorize?response_type=code&client_id=&redirect_uri=
We have successfully set up the AWS Cognito-hosted UI, and we should be able to use it to sign up, verify an account, and sign in. However, the UI does not look good, so we need to customise the style to suit our brand. AWS only allows us to use specific CSS classes to customise the UI. We can also sign in to the AWS console to download the default CSS template file for customisation. Go to Cognito -> YOUR COGNITO USER POOL -> Click on the App Integration tab -> Click on the Edit button in "Hosted UI customization".
You will see a CSS file link that allows you to download the default CSS template file to ease customisation. On the same page, we can upload our website logo, which will be displayed in the hosted UI.
Let's update the CSS file to look like the style below.
Update the CSS file to the following.
.logo-customizable {
max-width: 60%;
max-height: 30%;
}
.banner-customizable {
padding: 50px 0px 16px 0px;
background-color: transparent;
box-shadow: none;
border-radius: 8px;
}
.label-customizable {
font-weight: 500;
font-size: 16px;
margin-top: 16px;
}
.textDescription-customizable {
padding-top: 0px;
padding-bottom: 0px;
display: block;
font-size: 16px;
}
.idpDescription-customizable {
padding-top: 10px;
padding-bottom: 10px;
display: block;
font-size: 16px;
}
.legalText-customizable {
color: #747474;
font-size: 11px;
}
.submitButton-customizable {
font-size: 18px;
font-weight: 500;
margin: 20px 0px 10px 0px;
height: 48px;
width: 100%;
color: #fff;
background-color: #3e63dd;
}
.submitButton-customizable:hover {
color: #fff;
background-color: #3358d4;
}
.errorMessage-customizable {
padding: 16px;
font-size: 14px;
width: 100%;
background: #ffebeb;
color: #ce2c31;
border: none;
border-radius: 8px;
margin-bottom: 0px;
margin-top: 12px;
}
.inputField-customizable {
width: 100%;
height: 38px;
color: #000;
background-color: #fff;
border: 1px solid #e5e7eb;
font-size: 16px;
box-shadow: none;
}
.inputField-customizable:focus {
border-color: #3e63dd;
outline: 0;
}
.idpButton-customizable {
height: 40px;
width: 100%;
width: 100%;
text-align: center;
margin-bottom: 15px;
color: #fff;
background-color: #3e63dd;
border-color: #3e63dd;
}
.idpButton-customizable:hover {
color: #fff;
background-color: #3358d4;
}
.socialButton-customizable {
border-radius: 2px;
height: 40px;
margin-bottom: 15px;
padding: 1px;
text-align: left;
width: 100%;
}
.redirect-customizable {
font-size: 16px;
text-align: center;
}
.passwordCheck-notValid-customizable {
color: #ce2c31;
}
.passwordCheck-valid-customizable {
color: #19bf00;
}
.background-customizable {
background-color: #fff;
border-radius: 8px;
box-shadow: 0px 2px 20px rgba(0, 0, 0, 0%), 0 0 0 1000000px #fff;
border: 1px solid #e5e7eb;
}
Next, we need to update the cognito.tf
to include the customisation:
// Other codes
# Add the customisation
resource "aws_cognito_user_pool_ui_customization" "main" {
# TODO: The path to your custom CSS file
css = file("cognito-ui.css")
# TODO: The path to your custom logo
image_file = filebase64("cognito-logo.jpg")
user_pool_id = aws_cognito_user_pool_domain.main.user_pool_id
}
Last but not least, commit your terraform codes and apply them. Refresh your AWS Cognito-hosted UI, and you should see something like this, apart from the logo that should be your own uploaded logo.
In my opinion, AWS Cognito-hosted UI could be a good starter for small and medium businesses that would like to adopt OAuth 2.0 authorization. However, we need to work around the limitations of the hosted UI. AWS Cognito is an excellent service provided by AWS, but unfortunately, they are not prioritising the improvement of the hosted UI, which would make everything perfect if they did.
Copyright © 2024 Tek Min Ewe