AWS Service Orchestration with GraphQL and Hasura Cloud

AWS has tons of services which can be integrated with Hasura Cloud for various functionalities and use cases. In this post, we will look at how to leverage them from a 3factor app architecture and event driven serverless pattern.

Hasura Cloud gives you a GraphQL API instantly. But we need to connect a database to start building the app. Further, we need an authentication service to manage users and setup a permission system. Finally for all sorts of custom business logic, we can make use of serverless functions.

AWS Service Orchestration with GraphQL and Hasura Cloud
AWS Service Orchestration with GraphQL and Hasura Cloud

Broadly, we will make use of

  • AWS RDS for Database
  • AWS Cognito for Authentication
  • AWS Lambda for Events and Custom Business Logic

Before we get started, lets quickly setup a Hasura project.

Create a Hasura Cloud Project

  • Click on the following button to create a new free project on Hasura Cloud

Once you create a new free tier project, launch the console and head to the Data tab to connect the database. We will look at how to create the database on AWS RDS to complete this step.

Create AWS RDS PostgreSQL

  • Login to the AWS Console.
  • Create a new database with AWS RDS and select PostgreSQL. You can skip this step if you already have an existing database.
  • Allow public access and assign a VPC security group. This ensures that the database can be accessed from the outside world.
  • Configure Hasura Cloud IP in inbound rules. You can fetch the IP details from the project settings of Hasura Cloud dashboard. This is important because, the inbound rule will allow the Hasura Cloud instance to communicate with AWS RDS instance. Of course, if you end up adding the IP as 0.0.0.0/0 the database instance can be accessed by everyone on the internet.
  • The Database URL format postgresql://<user-name>:<password>@<public-ip>:<postgres-port>/<db> can be constructed so that it can be used to connect in the next step. The user name and db will most likely be default values of postgres and the port would be 5432. Primarily the password and the host IP value is the one that gets changed on the AWS dashboard.

For detailed steps, please refer to the docs on Using Hasura Cloud with AWS RDS PostgreSQL.

Now lets connect the database to Hasura Cloud using the project console.

Hasura Cloud Connect Existing Database
Hasura Cloud Connect Existing Database

Once the database is connected, we can head to table creation. Lets say we create a table called author with columns id, name, email, created_at.

As a next step, we will setup an Authentication service with Cognito.

Setting up Amazon Cognito

Amazon Cognito lets you setup user sign up/sign in for your applications quickly. It also supports social sign-in providers like Google, Apple, Facebook etc among other connectors. You can configure Cognito to generate JWT.

  • Create user pools
  • Add an app client and note down the client ID.
  • Configure app client settings, callback and signout URLs. Note that callback URLs can be localhost URLs too.
  • Enable Implicit Grant Flow for JWT
  • Choose a domain name that will be used for the hosted UI page.
  • Navigate to the Hosted UI page - https://your_domain/login?response_type=token&client_id=your_app_client_id&redirect_uri=http://localhost:3000/callback

In the above URL, replace the parameters like client_id and redirect_uri accordingly. Alternatively you can click on the Launch Hosted UI link on the Cognito Dashboard App Settings to directly land on the UI that facilitates user signup / signin.

Once this is done, we need to modify the claims that are used to generate the token. So here we will make use of Lambda to create a serverless function which injects the custom claims.

Add Custom JWT Claims for Hasura

  • Navigate to AWS Lambda
  • Create a new function.
  • Copy the following handler code to generate custom claims
exports.handler = (event, context, callback) => {
    event.response = {
        "claimsOverrideDetails": {
            "claimsToAddOrOverride": {
                "https://hasura.io/jwt/claims": JSON.stringify({
                    "x-hasura-user-id": event.request.userAttributes.sub,
                    "x-hasura-default-role": "user",
                    // do some custom logic to decide allowed roles
                    "x-hasura-allowed-roles": ["user"],
                })
            }
        }
    }
    callback(null, event)
}

Note that, we are using default values for x-hasura-role. You are free to write any custom business logic before assigning the role name to the key.

  • In Cognito, under Triggers, configure Pre Token Generation handler and select the lamdba function we just created above. This will ensure that the lambda function is triggerred everytime a token generation workflow is happening in the background.
  • Head to App Client Settings and click on Launch Hosted UI. Signup with a user and copy the id_token portion. Note that you will be redirected to the callback URL, likely the localhost URL that was configured earlier and hence you might get an error. But you can ignore the UI and focus on the URL parameters to extract just the id_token value.
  • Test the JWT in the debugger of jwt.io. Paste the id_token here to inspect the payload and verify the signature.

The next step is to facilitate Hasura Cloud to validate the tokens being used for the requests. For this, we need to configure Hasura Cloud with the Cognito configuration.

Configure Hasura Cloud ENV

  • Copy the following config for HASURA_GRAPHQL_JWT_SECRET env.
{
    "type":"RS256",
    "jwk_url": "https://cognito-idp.<aws-region>.amazonaws.com/<user-pool-id>/.well-known/jwks.json",
    "claims_format": "stringified_json"
}

Substitute the aws-region and user-pool-id from the URL parameters / General settings.

Create permissions for the role user

We had created the table author earlier. Now lets setup permissions for this table to allow only authors to query for their own data.

  • Head to the table permissions tab, create a new role called user and apply a filter for id column to map to x-hasura-user-id.

Finally we will create a serverless function to perform some custom business logic through async eventing system. We will make use of AWS Lambda for the functions.

Set up Lambda for Hasura Events

  • Create a simple function on Lambda.
  • Add a route on API Gateway to expose the function outside.
  • Add the endpoint to Hasura events to test an Event Trigger on a database table.

There are still more services like the S3 for storage from AWS which fit in well with the GraphQL and Hasura Cloud ecosystem.

I would like to understand from you folks on what are the different ways you use AWS services with Hasura Cloud and what do you like to get a more in-depth tutorial on. Do drop in the comments.

Blog
18 Nov, 2021
Email
Subscribe to stay up-to-date on all things Hasura. One newsletter, once a month.
Loading...
v3-pattern
Accelerate development and data access with radically reduced complexity.