See api-authorization Menu

Authorizing AWS API Gateway Requests With OneLogin API Oauth Access Tokens

The Amazon Web Services (AWS) API Gateway handles several concerns when building an API. It provides services for monitoring, maintaining, publishing, caching, and securing your APIs. It also plays a role in version control for the APIs and allows function results to be cached to improve performance. 

When you give users access to an API, the gateway must be able to determine who’s accessing the service (authentication) and who’s allowed to access various items of functionality (authorization). 

You could create AWS credentials for each user and assign them to roles appropriate for the needed permissions, but that approach isn’t manageable at scale. As you add more people to an organization or create more AWS accounts, managing all of those accounts becomes a nightmare. 

A better approach is an automated solution for managing users, authentication, and authorization. OneLogin OpenID Connect is the best-of-the-breed for authentication and authorization. The OpenID Connect API is both powerful and easy to implement (using OAuth access tokens) to authorize AWS API Gateway requests. 

While Amazon provides protections for the virtual network that hosts applications, you must take best practices and policies into consideration to further secure application resources. Enforcing password complexity rules and multi-factor authentication (MFA), enabling IP restrictions, and using single-sign-on (SSO) across your applications all help to avoid risky user workflows. They also help automate least-privileged access at scale. 

Authorizing API Gateway requests with OAuth access tokens

You can handle authorizing AWS API Gateway requests smoothly and reliably using OneLogin API OAuth access tokens. But is it hard to do this? Let’s find out together. You’ll need a working knowledge of the AWS API Gateway, and a computer with at least Java 7, Git, and NodeJS installed. 

When creating your own authorizer, you’ll implement it as an AWS Lambda. This is known as a Lambda authorizer. When a client uses one of your API functions:

  • The API Gateway calls your authorizer.

  • The authorizer receives the caller identity.

  • The authorizer returns an AWS Identity Access Management (IAM) policy. 

  • If the policy allows, the API call will pass through to its endpoint.


The Lambda may determine if a request is authorized by examining request parameters, by calling an OAuth provider for an access token, or by calling a Security Assertion Markup Language (SAML) identity provider.

Creating an AWS Lambda authorizer

Let’s create an authorizing Lambda and test it on one of the APIs in your Amazon instance. 

  1. Open the AWS Management Console. 


  2. Find and select Lambda in the list of services


  3. Select Create Function and choose Author from Scratch.

  4. Enter a meaningful name for the function


  5. Click Create Function to navigate to a screen with a code editor.

    For easy testing, we’ll keep the function simple.

    With this function, you pass a string and receive a response indicating whether permission is granted. A production authorizer for a Lambda would, of course, be more complicated.  

  6. Paste the following code (from this AWS sample) into the editor:

    exports.handler =  function(event, context, callback) {
        var token = event.authorizationToken;
        switch (token) {
            case 'allow':
                callback(null, generatePolicy('user', 'Allow', event.methodArn));
                break;
            case 'deny':
                callback(null, generatePolicy('user', 'Deny', event.methodArn));
                Break;
            case 'unauthorized':
                callback(Unauthorized);   // Return a 401 Unauthorized response
                break;
            default:
                callback(Error: Invalid token); // Return a 500 Invalid token response
        }
    };
    
    // Help function to generate an IA policy
    var generatePolicy = function(principalId, effect, resource) {
        var authResponse = {};
    
        authResponse.principalId = principalId;
        if (effect && resource) {
            var policyDocument = {};
            policyDocument.Version = '2012-10-17'; 
            policyDocument.Statement = [];
            var statementOne = {};
            statementOne.Action = 'execute-api:Invoke'; 
            statementOne.Effect = effect;
            statementOne.Resource = resource;
            policyDocument.Statement[0] = statementOne;
            authResponse.policyDocument = policyDocument;
        }
        authResponse.context = {
            stringKey: stringval,
            numberKey: 123,
            booleanKey: true
        };
        return authResponse;
    }
  7. Click Save.

Test the Code

Now open the API Gateway configuration on which you’ll test the code. 

  1. Choose Authorizers from the options on the left. 


  2. Select Create new Authorizer and enter a meaningful name for it. 


  3. Set the Type field to Lambda, then select the region for your authorizer function. 


  4. Next to this, select the function you created earlier. 


  5. Set the Lambda payload to Token. 


  6. For TokenSource enter authorizationToken. Remember that authorizationToken is the name of the parameter that will be passed to your Lambda. 

  7. Click the Create button and select Grant and create. 


  8. Once the authorizer is saved, click Test to try it out. You’ll see a field labeled authorizationToken.

  9. Enter the value “allow” and click Test to see the result. Then try it out again with “deny” or even a random value.

    Authorizing AWS API Gateway Requests With OneLogin API Oauth Access Tokens To apply this authorizer to one of your API calls, view the properties for one of the method requests. Expand its settings and you’ll see a property named Authorization. Set this property to the authorizer you created. Once that’s set, for a call to the API to succeed, the call must include authorizationToken in its header. Authorizing AWS API Gateway Requests With OneLogin API Oauth Access Tokens

Using OpenID Connect with Node.js

Let’s enable OpenID Connect within a Node application.  

Create an App within a OneLogin Account

If you don’t already have a OneLogin account, you can sign up for a free developer account

  1. In the OneLogin Admin UI, select the Applications tab.


  2. Click Add App. 


  3. Search for OIDC and select OpenID Connect. 
 Authorizing AWS API Gateway Requests With OneLogin API Oauth Access Tokens

  4. Enter a name for your application, then click Save. Authorizing AWS API Gateway Requests With OneLogin API Oauth Access Tokens

Configure the App

Once the application is saved, several other options become available. To configure the redirect URI for Oauth:

  1. Click the Configure option on the left. 


  2. In the Redirect URIs box that appears, enter the value https://localhost:3000/oauth/callback. 


  3. In the SSO tab, set Authentication Method to POST. 


  4. Take note of the client ID and client secret. You’ll need this information later. 


  5. Click Save to retain the settings you made. 

Clone the OneLogin Sample Repository from GitHub

For the application code, use the OneLogin sample repository from GitHub. This application uses ExpressJS to implement the web server and Passport.js to manage user authentication. 

  1. Clone the repository.

    It has several projects within it. You’ll use the one in the folder named 1 Auth Flow. The application contains a sample configuration to use as a starting point for your own configuration. 

  2. Rename the file .env.sample to .env and open it for editing.

  3. Set the content of the file as follows, replacing {your-client-id} and {your-client-secret} with the client ID and client secret from the previous steps.

    SUBDOMAIN={your-custom-domain}
 OIDC_CLIENT_ID={your-client-id}
 OIDC_CLIENT_SECRET={your-client-secret}
 OIDC_REDIRECT_URI=http://localhost:3000/oauth/callback

    To initiate a login, the application navigates to the URL /login. This URL is associated with a route that will invoke the OAuth authentication process. 

    app.get('/login', passport.authenticate('openidconnect', {
      successReturnToOrRedirect: /,
      scope: 'profile'
    }));

    After the user is authenticated, control returns to the application. There’s an access token for OneLogin API calls in req.session.accessToken. When the link to /profile is requested, that access token is used to retrieve the user’s profile through a get request to https://{your-sub-domain}.onelogin.com/oidc/2/me.  

    router.get('/profile', function(req, res, next) {
      request.get(
        `https://${ process.env.SUBDOMAIN }.onelogin.com/oidc/2/me`,   
        {
        'auth': {
          'bearer': req.session.accessToken
        }
      },function(err, response, body){
    
        console.log('User Info')
        console.log(body);
    
        res.render('profile', {
          title: 'Profile',
          user: JSON.parse(body)
        });
      });
  4. Save your changes to the configuration file. 


  5. Open a command terminal and navigate to the folder that contains the project. 


  6. To install the node dependencies for the project, use the command:


    npm install

  7. After the dependencies are installed, use the following to start the application: 


    npm start

  8. In your browser, go to https://localhost:3000. 


  9. Click LOGIN to try out the application. Since OneLogin is handling authentication, there’s nothing else you have to do within the app beyond configuring the application to have authentication capabilities. 


    Authorizing AWS API Gateway Requests With OneLogin API Oauth Access Tokens After logging in and selecting the /profile, the code will query OneLogin for the user’s information and display it on the screen. As you can see, the application is able to use OneLogin services.  Authorizing AWS API Gateway Requests With OneLogin API Oauth Access Tokens With OpenID Connect, basic information about a user is available through a REST-like API. Within an authorizer, information about an authenticated user can be used to decide if that user is authorized to access a service. 

Using OneLogin With Custom Authorization

Let’s change the authorizer that was created earlier. Instead of accepting a string, the Lambda will now use a JSON web token (JWT) from an authenticated user. A request to your AWS API must have the JWT passed in its header. The JWT is a string that has information on the user’s authenticated session within it. When decoded the information in the JWT becomes a JSON object. The updated Lambda will generate the appropriate authorization document to either allow or deny access. When we made the previous Lambda authorizer, we passed a simple string to control whether it allowed or denied a request. For the updated Lambda the JWT will be in its place.

With a JWT the user’s authentication status can be determined without making a round trip to the identity provider. Using the jsonwebtoken module the JWT string can be unpacked to retrieve several fields from the user’s authentication token. This includes the dates for which the token is valid, scopes, and additional information for further determining the validity and usage of the token. We have the option of querying OneLogin for additional information on a user if we wanted to add this to our authentication logic. For a simple example we will only check if the token has not expired and if the expected audience (client ID) is in the token.

  1. Replace the handler code from the previous code with the code below. The generatePolicy function from the previous code example will also be needed.

    var jwt = require('jsonwebtoken');
    
    const AUDIENCE = "e0001112-9e47-0138-5b6c-023242b000010000ab";
    
    exports.handler =  function(event, context, callback) {
        var token = event.authorizationToken;    
        var decodedToken = jwt.decode(TEST_TOKEN, {CLIENT_SECRET: true});    
    
        if(!decodedToken) {
            console.log("unauthorized caller");
            callback("Unauthorized");   
        }
    
        var expiration = new Date();
        expiration.setTime(decodedToken.exp * 1000);
        var now = new Date();
        if (expiration > now) {
            //token is expired. Don't authorize with it.
            console.log("expired token.")
            callback("Unauthorized"); 
        }
    
        if(decodedToken.aud == AUDIENCE)
            callback(null, generatePolicy(event.authorizationToken, 'Allow', event.methodArn));
        else
        callback(null, generatePolicy(event.authorizationToken, 'Deny', event.methodArn));
    };

When an attempt is made to call the API function now the Lambda can quickly determine if the call is authorized. With this small amount of code access to your AWS APIs can be managed through OneLogin. Since the token validity is short lived and since user information is saved on AWS as users are added and removed there is no data to sync.

Next Steps

In this article, we walked through the steps necessary to authorize AWS API Gateway requests with OneLogin API OAuth tokens.

To learn more about OneLogin APIs, check out the OneLogin Documentation Page.