//

3 Steps to Access AWS Resources with Google Sign-In

11.4.2018 | 12 minutes of reading time

Imagine you implement a mobile app that needs to access AWS resources like an S3 bucket. You could of course distribute some API keys with your app, but this is not a good idea for many reasons. AWS strongly advises against it as well.

For that purpose, AWS provides the Security Token Service, which delivers the functionality to generate temporary AWS API keys that expire after a given amount of time. One possibility is to use this together with a federated identity provider like Google Sign-In.

This tutorial is separated in a total of three steps.

  • In the first step, we will create a very simple, serverless, hello-world-style web service with AWS API Gateway and Lambda. This will serve as a base for the authentication use cases.
  • In the second step, we will add some control over who can use the web service.
  • In the third step, we will use “login with Google” to get temporary credentials for the web service.

Prerequisites

To complete this tutorial, you need the following settings.

AWS Account

To start with this tutorial, you need an AWS account. You can find more details on how to create an AWS account in the AWS documentation .

All of the services used in this tutorial are free tier eligible, so you can use them free of charge. Many of the services you use in AWS are hosted in a specific region. All the steps for this tutorial were done in the Frankfurt Region (eu-central-1), since it is closest to our location. If you use a different region, you might need to specify it differently when authenticating with AWS.

Rest Client

This tutorial is about the idividual services that are required to get the use case running, not about implementing a UI on top of it. Therefore, some steps will be done using a REST client. For this tutorial, we recommend using Postman , since it has AWS authentication built in.

Google Account

To use Google Sign-In, you need a Google account. It does not have to be a specific one, so if you already have one, just use it.

Text File for Notes

From time to time during this tutorial, we will ask you to copy a value into a text file for later use. You can use the following template for a text file, so that you don’t confuse the different values that you need.
1. Invoke URL: 2. Access key ID: 3. Secret access key: 4. S3 Endpoint URL: 5. Client ID: 6. Role ARN: 7. ID Token:

Step 1: Getting Started without Access Restrictions

In this step, you are going to build a simple web service using AWS API Gateway and AWS Lambda. The API Gateway takes care of receiving a HTTP request, while Lambda provides the functionality behind it. Basically, the HTTP request triggers the Lambda function, and the result of the Lambda function becomes the web service response.

Creating the Lambda

First, create a Lambda function in AWS. Navigate to the Lambda service and click on “Create a function”. Create a new Lambda by selecting “Author from scratch”.

You can now configure your Lambda. Let’s call it “simple-hello-world” and use “Python 2.7” as runtime. You also have to define the permissions for the Lambda. To do this, select “Create new role from template(s)”. As role name, enter “simple-lambda-role”. Hit “Create function” when you’re ready to proceed.

Your Lambda was created. On the next page, you can explore configuration and monitoring parameters, but you can leave everything as is.

As you can see, the lambda will just return the string “Hello from Lambda”. If you want, you can test the lambda here by using the “Test” button on top. Just create a test event (the content does not really matter here) and then click test. Hopefully you see that your execution succeeded.

Creating the Web API

The next step is to create the API in API Gateway. In the AWS console, navigate to the API Gateway service and start to create a new API. If this is your first time working with the API Gateway, AWS will show you an example API. Just select the radio button “New API” to start creating your own.

As name, enter “simple-hello-api” and press “Create API”.
On the next page, press “Actions” → “Create Method”. Select “GET”.

Here you can now integrate the Lambda function that you created before. Therefore enter “simple-hello-world”. As soon as you start entering the name, you should be able to select it directly. Press “Save”. This will trigger a box to inform you that API Gateway will receive the permission to execute your Lambda function simple-hello-world. Select “OK”.

You now configured your API, but this is just the first step. You first have to deploy it to make it actually work. Select “Actions” → “Deploy API”.

In order to deploy the API, you need to choose a stage. Just select “[New Stage]” and enter “main” as Stage name. Hit “Deploy”.
This is it. On the next page, you can see the Invoke URL of the newly created web service. Copy this URL into the text document you prepared. Store it as “1: Invoke URL”.

To test your web service, visit the Invoke URL in your browser. You should see the “Hello from Lambda” output from your Lambda function.

Step 2: Adding Access Control

To access AWS resources, you have to have the appropriate permissions. AWS IAM is the AWS service that deals with permissions, policies, roles etc. You will now add IAM to your web service so that you can be sure that the requester has the right permissions to access your service.

Adding IAM Authorization

If you visit the Resources page of the API, you can see that Authorization is set to “None” – this means that everybody is allowed to access the API.

To change this, click on the GET, then select “Method Request”. Change the value of Authorization from “NONE” to “AWS_IAM”. Click on the small check mark to save your change.

When this is done, the change is not yet reflected in the API. It first has to be deployed again. Select “Actions” → “Deploy API” and select “main” as Deployment stage.
If you visit the Invoke URL again, you now get an error response. This is because now you need to supply a valid AWS API key that gives you the required permissions.

Creating an AWS User

To get such an API key, let’s generate a dedicated AWS user. In the AWS console, open the IAM service, navigate to “Users” and select “Add user” to create a new user for this purpose. Enter the User name “simple-webservice-user” and as Access type, select “Programmatic access”.

Navigate to the next page with “Next: Permissions” and select “Attach existing policies directly”. Search for and select the policy named “AmazonAPIGatewayInvokeFullAccess” by setting the check mark and press “Next: Review”:

Finish the user creation by clicking on “Create user”. You will see a success message. Before you close, make sure to copy the Access key ID and the Secret access key into the text document. Store it as “2. Access key ID” and “3. Secret access key”.
This is the only time that the secret key is displayed. If you forget to copy the secret key, you can always create a new key in IAM by clicking on the name of your user → “Security credentials” → “Create access key”.

Authenticating with Postman

From now on, the browser is not enough any more to access the web service. It is now time to switch to Postman and test the API. You can of course use any REST client, but Postman already has the functionality included to generate AWS authentication headers based on API keys. Enter the Access key ID and Secret access key that you copied before. Also make sure to use the correct AWS region of your API in the Advanced section of the authorization configuration, otherwise it will not work.

If you entered the right keys and region, you will get the “Hello from Lambda” answer from the API. The web service is now secured and can only be accessed by authorized users.

However, this can only be an intermediary step. If you wanted to rely on this in a mobile application, you would need to include the API key in the app itself. This is not the way you should do this. Therefore, let’s go on to the next step.

Step 3: Google Sign-In

The way you would like your mobile application to access the web service is by generating a temporary API key that is only valid for a small amount of time. You will achieve this by using the AWS Secure Token Service together with Google Sign-In.

Configuring the Google Login Button

Let’s start by using Google Sign-In. This is Google’s identity provider service. To access it, you will host a small static website in an AWS S3 bucket that displays a “login with Google” button. This website will print out the Google authentication information so you can note it down. Using an S3 bucket is necessary because Google needs to know the URL under which the login button will be, and an S3 bucket gives us a fixed domain name.

In the AWS console, go to S3 and create a new bucket. Choose a unique name for the bucket and directly click on the “Create” button in the left bottom corner.

Once the bucket is created, select it by clicking on its name and go to “Properties”. Select “Static website hosting” and enable “Use this bucket to host a website”. Use ”index.html” as Index document and “error.html” as Error document.

Copy the Endpoint URL to the text document (don’t confuse it with the Invoke URL from a previous step). Store it as “4. S3 Endpoint URL”. You will need this URL later when creating the credentials in your Google project. Hit the “Save” button.

Next, you have to configure Google Sign-In. Go to https://console.developers.google.com and create a new project. Name it “simple-hello-project” and press “Save”.

Next, go to “Credentials” → “OAuth consent screen” to configure an OAuth consent screen. As product name, enter “simple-hello-product”. Press “Save”.

Go back to the “Credentials” tab and select “Create credentials”. Select “OAuth client ID”. As Application type, select “Web application”. As name, enter “simple-web-client”. In Authorized JavaScript origins, enter the S3 Endpoint URL. Press “Create”.

In the next screen, you will receive a client ID. Copy it to your text file as “5. Client ID”, as you will need it in the next step.

Configuring an IAM Role

To allow a google user to access the API, you need to create an IAM role with the necessary permissions. In AWS terms, the Google user will later assume that role.
In the AWS console, go to IAM → Roles. Select “Create role” and select “Web identity”. As Identity provider, select “Google”, as Audience enter the client ID copied in the previous step.

On the permissions page, add the permissions AmazonAPIGatewayInvokeFullAccess, AmazonAPIGatewayPushToCloudWatchLogs and AWSLambdaBasicExecutionRole by setting the check mark. Press “Next: Review” and finally, name the role “simple-hello-role” and create it.

Check the details of the newly created role by clicking on it. Copy the Role ARN into the text document as “6. Role ARN”, as you will need it later.

Putting It Together

Next, create a new file called “index.html” on your local hard disk. Enter the following text:

1<html lang="en">
2  <head>
3    <meta name="google-signin-scope" content="profile email">
4    <meta name="google-signin-client_id" content="YOUR_CLIENT_ID.apps.googleusercontent.com">
5    <script src="https://apis.google.com/js/platform.js" async defer></script>
6  </head>
7  <body>
8    <div class="g-signin2" data-onsuccess="onSignIn" data-theme="dark"></div>
9    <script>
10      function onSignIn(googleUser) {
11        // Useful data for your client-side scripts:
12        var profile = googleUser.getBasicProfile();
13        console.log("ID: " + profile.getId()); // Don't send this directly to your server!
14        console.log('Full Name: ' + profile.getName());
15        console.log('Given Name: ' + profile.getGivenName());
16        console.log('Family Name: ' + profile.getFamilyName());
17        console.log("Image URL: " + profile.getImageUrl());
18        console.log("Email: " + profile.getEmail());
19 
20        // The ID token you need to pass to your backend:
21        var id_token = googleUser.getAuthResponse().id_token;
22        console.log("ID Token: " + id_token);
23      };
24    </script>
25  </body>
26</html>
27

Instead of the “YOUR_CLIENT_ID.apps.googleusercontent.com” placeholder, enter the Client ID from the previous steps. Now, upload the file to your S3 bucket and make sure it is public. Therefore navigate to S3, click on the name of your bucket and press “Upload”. Select your index.html and you’re ready to upload the file. Click on the name of your file and then press “Make public” to enable users to access the page.

A quick word of warning: The Link displayed in the screenshot above is different from the S3 Endpoint URL! Don’t get confused and stick to the URL copied before!
Now, visit the S3 Endpoint URL. You should see something like the following:

Open the browser’s developer console (depends on your browser where you can find it) and press the Google button. You are given a sign-in screen directly from Google where you can login using your Google account.
Once signed in, the developer console displays the login information:

Copy the ID Token to the text document as “7. ID Token” for use in the next step.

Generating Temporary API Keys

In the following, you will use the AWS Security Token Service (STS), which will generate temporary API keys. Those keys can then be used like the static ones we generated in step 2.

You need to execute the function “AssumeRoleWithWebIdentity” inside the AWS STS. To do so, use Postman to send a GET request to the following URL, replacing the variables with the IAM Role ARN, and with the ID Token from the previous step.

https://sts.amazonaws.com/?Action=AssumeRoleWithWebIdentity&DurationSeconds=3600&RoleSessionName=simple-hello-session-name&RoleArn=&WebIdentityToken=&Version=2011-06-15

The XML response contains all that you need to authenticate against the webservice. Copy AccessKeyId, SecretAccessKey and SessionToken and insert them into the AWS Signature authorization fields in Postman. Do not forget to provide the corresponding AWS region.

Summary

Distributing API keys with your app is not a good idea. It is preferable to generate API keys when you need them. This tutorial showed you how you can do this using AWS STS together with a federated login provider like Google Sign-In.

We hope this blog post helped you to understand how to implement this use case. If you have any comments or suggestions, feel free to let us know!

share post

Likes

0

//

More articles in this subject area\n

Discover exciting further topics and let the codecentric world inspire you.

//

Gemeinsam bessere Projekte umsetzen

Wir helfen Deinem Unternehmen

Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.

Hilf uns, noch besser zu werden.

Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.