Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Google Authentication for Your AWS Management Console With OAuth 2.0

DZone's Guide to

Google Authentication for Your AWS Management Console With OAuth 2.0

Learn how to deploy an alternative sign-in mechanism for AWS management console that's using Google accounts for authentication.

· Security Zone ·
Free Resource

Do you know who is accessing your valuable data through your APIs? Discover how

We're going to deploy an alternative sign-in mechanism for AWS management console that's using Google accounts for authentication. Fine-grained authorization is still managed on the AWS side using IAM, but user identification is delegated to Google's identity service.

How Can This Be Useful?

Although there are many pros and cons to this approach, some of the possible benefits are:

  • A better understanding of federated authentication mechanism.
  • Simplifying credential management for teams who already have Google accounts.
  • Customizing authentication mechanisms at very low maintenance costs.
  • Serving as a good alternative to deploying and configuring our own IDP service (e.g. with Shibboleth).

Authentication Flow

Image title

  1. Users are downloading the HTML page from S3 that's going to control the authentication mechanism.
  2. User's browser is authenticating with Google.
  3. An authentication token is then passed to STS.
    • STS verifies the token with Google.
    • Also, STS checks if the submitted IAM role has the necessary privileges.
  4. Lambda is called through the API Gateway which is going to generate a temporary sign-in token for the AWS management console.
    • The API Gateway will verify if the caller has the necessary credentials to use the Lambda function.
  5. The user is redirected to the management console.

Implementation Steps

Create an S3 Bucket for the Static Website

Create a new bucket in your AWS account. Enable static website hosting for that bucket. Set index.html as the "Index document."

Image title

Set permissions for the new bucket. Go to "Permissions" -> "Bucket Policy" and enable s3:GetObject action for all users. You can restrict access to a specific IP range as well.

{
    "Version": "2012-10-17",
    "Id": "Policy1525679703889",
    "Statement": [
        {
            "Sid": "Stmt1525679702460",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::credentials-frontpage/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "1.2.3.0/24"
                }
            }
        }
    ]
}

Image title

Test your configuration by accessing the bucket in the browser. You should get an HTTP 404 response.

Image title

Create Google Client ID

Note that registering to Google Cloud is not necessary to create the OAuth client ID.

Image title

First, go to the Google developer console. Sign-in with your account that you would like to use for API management. 

Select "APIs & Services" -> "Credentials" from the menu. If you haven't done so, you also have to create a project.

Create "OAuth client ID" as a new credential. You will also have to fill in the "OAuth consent screen" for the first time. 

Image title

Image title

The application type should be "Web Application." Also, you should set the S3 web URL in the "Authorized JavaScript origins" field.

Image title

Install Static Website to S3

Next, we should configure the static website and install it to the newly created S3 bucket. 

Download the static website from here. Copy the Google Client ID from the newly created credentials and add it to the index.html page.

Image title

<head>
    ...
    <!-- GOOGLE CLIENT ID -->
    <meta name="google-signin-client_id" content="YOUR-CLIENT-ID">
    ...
</head>

Upload awsconfig.jsindex.html , and authentication.js  to the S3 bucket.

Image title

Open the website again in your browser and see if the first authentication step from the authentication flow diagram is completed successfully. Sign in with any Google account. Open the JavaScript console (press F12) and check the response from Google's authentication API. You will need the Google ID returned from the API for the next step.

Image title

Add Policies

We need to create the related IAM role in AWS and assign the necessary policies so the STS API can send us temporary access/secret key pairs.

Image titleLog into your AWS console and navigate to IAM management. Create a new IAM role by selecting Roles and clicking on the "Create role" button.

Fill in the form by choosing "Web Identity." Copy your Google Client ID to the "Audience" section. Restrict role usage by adding a condition that will check the Google ID of the user who would sign-in. You should paste the Google ID to the "Value" field as it is. Without this condition, anyone with a Google account could sign-in to your AWS management console!

Image title

The user's Google ID is printed out in the JavaScript console during authentication when you visit your installed static website in the previous step. You can specify more user by using a JSON array.

Verify if the generated trust policy is correct, by clicking on "Trust relationships" and then "Edit trust relationship." You should see something similar as the JSON below.

Image title

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "accounts.google.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "accounts.google.com:aud": "YOUR_GOOGLE_CLIENT_ID",
          "accounts.google.com:sub": [
                  "GOOGLE_USER_ID",
                  "ANOTHER_GOOGLE_USER_ID"
              ]
        }
      }
    }
  ]
}

Add policies for the IAM role (you can skip this step for now). You should assign policies based on what users with this role will be able to to do. Update the roleArn property in your awsconfig.js in the static website. You should copy and paste your role ARN to awsconfig.js and then upload the file to your S3 bucket.

Image title

Test the STS token generation. Go back to the static website in the previous step and verify if STS is returning an access and secret key pair.

Image title

Install a Lambda Function

In the next step, we will create a Lambda function that's going to generate a sign-in token for accessing the AWS management console.

Go to Lambda in your AWS management console and create a new function. Give it a name and assign a role to it. It doesn't really matter what role you choose. The lambda is going to call a public AWS API.

Image title

Image title

Copy and paste the lambda definition from here and save the function.
Image title

Create an API Gateway

Go to the API Gateway in your AWS management console and click on "Create API." Give your new API a meaningful name.

Image title

Image title

Image title

Image titleFrom the "Actions" drop-down select "Create Method."

Select POST as the method type.

Select "Lambda Function" as the "Integration type." Check "Use Lambda Proxy Integration." Select your previously created function as the "Lambda Function."

Image title

Image titleSelect "Enable CORS" from the "Actions" menu. Add X-Amz-User-Agent to the "Access-Control-Allow-Headers."

Image title

Add IAM Authorization to Your API

We will ensure that only Google users associated with our new IAM role can call our newly created API.

Select your POST method and click on "Method Request." Select "AWS_IAM" from the drop-down and select the checkbox to save your changes.

Image title

Image titleCopy and save the ARN from both thePOST and OPTIONS methods.

Image title

Go to IAM management and select the role we've created in the previous steps. Select "Add inline policy." Copy and paste the following JSON and add ARNs forPOST and OPTIONS operations you've saved in the previous step. It should look like something similar.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "execute-api:Invoke",
            "Resource": [
                    "arn:aws:execute-api:REGION:ACCOUNT_ID:API_ID/*/OPTIONS/",
                    "arn:aws:execute-api:REGION:ACCOUNT_ID:API_ID/*/POST/"
                ]
        }
    ]
}

Image title

Image title

Deploy API and Test the Authentication Mechanism

Deploy your API by selecting "Deploy API" from "Actions" drop-down. Select "[New Stage]" and enter a name for your new deployment stage.

Image title

Image title

After deploying, copy and save your API URL for configuring your static website.

Image title

Open the awsconfig.js file and set the regionapiGatewayUrl and apiGatewayPath variables. It should be similar to the following:

window.config = {
    roleArn: "arn:aws:iam::ACCOUNT_ID:role/Google-Auth",
    region: "eu-west-1",
    apiGatewayUrl: "https://YOUR_API_ID.execute-api.YOUR_REGION.amazonaws.com",
    apiGatewayPath: "/prod"
}

Upload awsconfig.js to your static website in S3. Test your new authentication mechanism. At this point, you should be able to log in to your management console with your Google account.
If anything goes wrong, open the developer toolbar in your browser and check the JavaScript console and the "Network" tab for errors.

For example, I had an issue with the attached policy definition that allows my role to call the deployed API and it looked like this in the browser:

Image title

Reasoning

Why Do I Need a Lambda?

The AWS federation sign-in API is not giving back proper CORS headers. That's why we had to create a proxy call with Lambda and enable CORS in the API gateway.

Why Not Use SAML Authentication With Google?

My initial goal was to find the cheapest possible solution with the least management overhead. SAML authentication is only available at Google for G Suite users and only allows a 14-day trial.

Why Not Host Everything in a Single Instance?

Hosting application code in one 't2.nano' instance would cost around $4.50 per month.
Using Lambda and API Gateway reduces the expected cost to cca. $0.01 per month.

You can create your own estimated budget comparison at servers.lol

Known Issues

Changing the "Authorized JavaScript origins" for your OAuth client ID looks like broken. If you changed its value, you'd get an error message when trying to sign-in with your Google account. In these cases, you have to create a new "OAuth client ID" in the Google admin console and change Client ID in your index.html. Don't forget to upload it to S3 again.

Start a free self-guided trial to discover how API Security is done through a true Zero Trust approach.

Topics:
aws iam ,security ,cloud security ,oauth ,authentication

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}