Implement Google Auth with AWS Lambda and Supabase in 30 minutes
Tags: javascript, aws, serverless, tutorial
Published: 2023-10-10 12:20:13

## Google auth is hard to implement…

In today's world, authentication with Google and other providers are widely used. However, implementing them can be time-consuming, especially when dealing with multiple providers. 😫

I used Supabase to implement Google Auth in my project using AWS Lambda in less than 30 minutes. Here is how 👇🏼


![Implementation schema](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lr6iph3sfm83logl4qj4.png)

## How to configure Supabase 🏁

Getting started with Supabase is straightforward. Here are the steps:

1. **Sign Up:** Begin by creating an account on the Supabase platform. The registration process is user-friendly and intuitive. 📝
2. **Retrieve Your Account URL and Token:** After successful registration, make sure to obtain your account URL and token. These credentials are crucial for integrating Supabase with AWS Lambda authentication. 🔑
    
   
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ep2g6ifsfn6g5sae9l58.png)
    
3. **Activate Google Authentication in Supabase:** [Supabase Documentation](https://supabase.com/docs/guides/auth/social-login/auth-google) 🌐

Now that you have your Supabase credentials, let's start by connecting your frontend to Google 🚀

## Add a Google button to your login page

Using Supabase is very easy. You only need to install `@supabase/supabase-js` and follow the steps below.

1. Create a Supabase client:
    
    ```typescript
    import { createClient } from "@supabase/supabase-js";
    
    export const supabaseClient = createClient(
      "<https://xxxxx.supabase.co>",
      anon_key
    );
    
    ```
    
2. Handle the 'Login with Google' button click event:
    
    ```typescript
    <button
    	onClick={() => supabaseClient.auth.signInWithOAuth({
        provider: 'google',
    	})}
    >Login with Google</button>
    
    ```
    

Users will be redirected to the Google authentication page and will return to your website with a token upon successful authentication. 🌐🔐

The token should be included in all your backend calls through the request header. 🚧

## Handle the Supabase token in your backend

1. Create a **Lambda Authorizer:**
    
    
    When a request is made to an AWS Lambda function, it typically passes through an API Gateway. In this setup, I intercept the incoming request at the API Gateway level and manually validate the token included thanks to **custom authorizers**.
    
    A custom authorizer is also a lambda function that will be executed before the routes it protects. I need to create a new Lambda function, called `customAuthorizer` for example.
    
    Here's a code snippet demonstrating how I extracted the user ID from the token in the authorizer:
    
    ```typescript
    // I assume here that you've retrieved your secret key `SECRET` from Supabase
    
    // I also suppose that accessToken is formatted as `Bearer xxxxxxxxxx`
    
    export const getUserIdFromToken = (accessToken: string | undefined): string => {
      if (accessToken === undefined) {
        throw new Error('Missing token');
      }
      const token = accessToken.split(' ')[1];
    
      if (token === undefined) {
        throw a Error('Badly formatted token');
      }
      try {
        const decoded = jwt.verify(token, SECRET);
    
        if (typeof decoded === 'string') {
    			// you need to throw if the user in unauthorized
          throw new Error('Decoded token should not be a string');
        }
    
        if (decoded.sub === undefined) {
          throw new Error('Cannot find sub');
        }
    
        return decoded.sub;
      } catch (error) {
        throw new Error('Invalid token ' + JSON.stringify(error));
      }
    };
    
    ```
    
    I declared my customAuthorizer function as the authorizer in the ApiGateway config. For example, the code using the Serverless Framework looks like this:
    
    ```typescript
    httpApi: {
        ...,
        authorizers: {
          customAuthorizer: {
            type: 'request',
            functionName: 'customAuthorizer', // the name of my authorizer lambda
          },
        },
      }
    
    ```
    

1. Use this new authoriser as the route protector of my API routes
    
    ```typescript
    export const chatCompletion = {
      environment: {},
      handler: __dirname + '/handler.ts', // The path of the handler
      events: [
        {
          httpApi: {
            method: 'post',
            path: '/chat/completion',
            authorizer: { name: 'customAuthorizer' }, // the authoriser i just created
          },
        },
      ],
    };
    
    ```
    

### And we are done!!! 🥳

If you want to go deeper into custom authorizers, check out this very cool doc from AWS: [AWS Lambda Authorizers with a Third-Party Identity Provider](https://aws.amazon.com/blogs/security/use-aws-lambda-authorizers-with-a-third-party-identity-provider-to-secure-amazon-api-gateway-rest-apis/) 👀

### Caution ⚠️🔐

When using a custom authorizer with Supabase, we need to use a Supabase **secret key**, which should be carefully stored in a secured location such as **AWS Secret Manager**.

## AWS **Cognito vs. Supabase: A Quick Comparison**

When choosing between Amazon Cognito and Supabase for authentication, it is important to consider the following:

| Criteria | Cognito | Supabase | Comments |
| --- | --- | --- | --- |
| Cost for 100k Users/month | $550 | $325 | Supabase stands out as a cost-effective choice because of its lower pricing, potentially saving you money. 💰 |
| Latency | Low | High | Supabase introduces a new lambda execution due to custom authorizer, which may result in higher latency, making Cognito preferable for low-latency applications. ⏳ |
| Provider Integration | Requires more setup | Streamlined, supports multiple providers | Supabase streamlines provider integration, making it a convenient option, especially if you need to work with multiple providers. 🚀 |
| Infrastructure as Code | Yes | No | Cognito supports Infrastructure as Code (IAC), allowing for more automated and scalable deployments, giving it an edge in this aspect. 🛠️ |
| Serverless Integration | Seamless | Seamless | Both platforms integrate well with serverless, so the choice here depends on other factors in your project. 🤖 |
| Developer Community | Large | Growing | Cognito has a well-established community, which can provide robust support and resources, making it an appealing choice. 👥 |
| Scalability | Excellent | Excellent | Both platforms excel in scalability, so your decision may depend on other factors like cost or ease of use. 📈 |
| Compliance | Strong compliance framework | Evolving compliance features | Cognito offers a mature compliance framework, making it a better choice if you require a strong compliance foundation for your project. 📜 |
| User Experience | Feature-rich but more complex | Simple and straightforward | Supabase offers a more user-friendly experience, making it a preferred choice if simplicity and ease of use are top priorities. 😄 |
| Performance Considerations | Generally lower latency due to well-integrated AWS services | May introduce higher latency due to custom authoriser and secret retrieval | Performance optimizations include minimizing Lambda invocations, ensuring scalability with JWT, and implementing caching for improved response times and reduced load. ⚙️📈🚀 |

## Explore Additional Alternatives:

Although I've emphasized Supabase, it's essential to be aware of other authentication services that seamlessly integrate with AWS Lambda. Consider investigating alternatives like Clerk, Auth0, and Firebase to identify the best match for your project requirements. 🕵️‍♂️🔍🌟