Secure your NextJS Apps with Azure AD and NextAuth (Part 6)

Deploying with Serverless Stack

Dewaun Ayers
5 min readMar 5, 2023

Disclaimer: This is part 6 of a 7 part tutorial. Click the below link to go back to Part 1 to learn more about the intent of this tutorial.

Part 1 — Introduction and “What is an Identity Provider?”

Or go back to Part 5 — Securing your API Routes with NextAuth

Serverless Stack (SST) Refresher

In Part 3 we briefly described Serverless Stack (SST).

SST is an abstraction layer sitting on top of AWS CDK that offers excellent, intuitive constructs for deploying full stack web applications to AWS.

For this tutorial we will be deploying the NextJS application, AppSync + GraphQL, and using Open ID Connect (OIDC) as an authorizer for AppSync.

The OIDC authorizer will be covered in Part 7.

Before we get started

Remember in Part 3 where you were asked to create an AWS account? Well, if you haven’t done that, now’s the perfect time. Here’s the bit from Part 3 in case you don’t want to go back

To setup the required credentials you can follow the offical AWS instructions for setting up an account and user and storing AWS credentials.

To make things easier for you, setup the default profile as the one you want to deploy with for this tutorial. Otherwise if you set up an alternative profile, you can prefix the npm scripts in the root package.json with AWS_PROFILE=<your_profile_here>

Configuring your SST Constructs — AppSync API

We are going to use AppSync as a Proof of Concept for authenticating a user through a third-party service. This will be covered in Part 7.

In stacks/MyStack.ts add the following imports to the top of the file

import { AppSyncApi, Function, NextJsSite, StackContext } from "sst/constructs"
import * as appsync from "@aws-cdk/aws-appsync-alpha"

Now let’s setup AppSync and add a simple Notes table in DynamoDB with a Lambda resolver to return any notes in the table.

In stacks/MyStack.ts add the following code

export function MyStack({ stack, app }: StackContext) {
// Create the notes table
const notesTable = new Table(stack, "Notes", {
fields: {
id: "string",
},
primaryIndex: { partitionKey: "id" },
});

// Create the AppSync GraphQL API
const api = new AppSyncApi(stack, "AppSyncApi", {
schema: "graphql/schema.graphql",
defaults: {
function: {
// Bind lambda function to table
bind: [notesTable],
},
},
// Add lambda as data source
dataSources: {
notes: "functions/lambda.handler",
},
resolvers: {
"Query listNotes": "notes",
},
});
}

The Table construct configures a DynamoDB instance with a table called Notes. The AppSyncApi construct will spin up an AppSync instance with a lambda resolver which has permission to access the notes table.

In the services directory create a graphql folder and add a schema.graphql file with the following content

# services/graphql/schema.graphql
type Note {
id: ID!
content: String!
}

type Query {
listNotes: [Note]
}

Update the code in services/functions/lambda.ts to connect to our DynamoDB table and list all the notes

// services/functions/lambda.ts
import { DynamoDB } from "aws-sdk";
import { Table } from "sst/node/table";

type Note = {
id: string;
content: string;
};

type AppSyncEvent = any;

const dynamoDb = new DynamoDB.DocumentClient();

export async function handler(
event: AppSyncEvent
): Promise<Record<string, unknown>[] | Note> {
const params = {
TableName: Table.Notes.tableName,
};

const data = await dynamoDb.scan(params).promise();

return data.Items;
}

Configuring your SST Constructs — Next.js Site

Next let’s set up our Next.js application deployment.

In the stacks/MyStacks.ts file add the following code just below the AppSyncApi code.

// Create a Next.js site
const site = new NextjsSite(stack, "Site", {
path: "packages/frontend",
environment: {
REGION: app.region,
API_URL: api.url,
},
});

// Allow the Next.js API to access the table
site.attachPermissions([table]);

// Show the site URL in the output
stack.addOutputs({
URL: site.url,
});

The NextJsSite construct will handle deploying our NextJS application and the required infrastructure into AWS. SST will add the environment variables to the Next.js application for us. This means we will be able to access the URL to our AppSync GraphQL endpoint by using process.env.API_URL in client/server components and API routes.

Local Deployment

Before moving on to a full deployment we should test a local dev deployment.

Add the sst env command to the frontend package.json dev script. This will allow you to pass environment variables defined in your SST constructs (like API_URL, etc…) to your local Next.js dev server.

Replace the dev script in your frontend/package.json.

"dev": "next dev",

With the following:

"dev": "sst env next dev",

At the root of the project run npm run dev to deploy your personal dev stack to AWS via SST. I won’t go into detail about how this works, but just know that SST does some cool stuff to give you a development experience that is incredibly close to working with a live environment.

Open a separate terminal and run npm run dev in the frontend directory.

You should be able to console.log the API_URL in your hello.ts API route like so

console.log("API_URL", process.env.API_URL)

Deploying for real!

To deploy the application for real, run npm run deploy at the root of the project. This will deploy your infrastructure to AWS. There will be some output in the terminal that displays your site URL. It might look something like

URL: https://d111111abcdef8.cloudfront.net

In order to test auth in your live site, you will need to take that Site URL and add it to the Redirect URIs in Azure AD.

To do this, navigate to your App Registration in Azure AD, click on your App, and then select Authentication on the left-side navigation menu. From there, click Add URI under the Platform Configurations Redirect URIs section.

Click the save button at the bottom of the screen and you should be good to navigate to your site, via the url, and sign in!

Next up we’re going to make sure that only authenticated users can access our AppSync API.

Head over to Part 7 to get started.

What’s next?

Part 7 — Third-Party Authentication and Authorization with AWS AppSync

My goal is to provide content that leaves readers with a bit more knowledge than they started with.

If this tutorial helped you in anyway please leave a clap or two! If you have any questions or I got something wrong, leave a comment and let me know how I can improve!

--

--

Dewaun Ayers
Dewaun Ayers

Written by Dewaun Ayers

I'm a Frontend Dev living in Melbourne, Australia and studying Computer Science. I love anything to do with web tech and am constantly trying to learn more!

No responses yet