Authenticate Neon Postgres application users with Okta
Learn how to add authentication to a Neon Postgres database application with Okta
User authentication is critical for web applications, especially for apps internal to an organization. Okta Workforce Indentity Cloud is an identity and access management platform for organizations, that provides authentication, authorization, and user management capabilities.
In this guide, we'll walk through building a simple Next.js application using Neon's Postgres database, and add user authentication to it using Okta. We will cover how to:
- Set up a Next.js project with Okta for authentication
- Create a Neon Postgres database and connect it to your application
- Define a database schema using Drizzle ORM and generate migrations
- Store and retrieve user data associated with Okta user IDs
note
Okta provides a different solution called Customer Identity Cloud, powered by Auth0
, to authenticate external customers for Saas applications. This guide focuses on the Workforce Identity Cloud for internal applications. For an example guide using Auth0
, refer to our Auth0 guide.
Prerequisites
To follow along with this guide, you will need:
- A Neon account. If you do not have one, sign up at Neon. Your Neon project comes with a ready-to-use Postgres database named
neondb
. We'll use this database in the following examples. - An Okta administrator account for user authentication. Okta provides a free trial that you can use to set one up for your organization.
- Node.js and npm installed on your local machine. We'll use Node.js to build and test the application locally.
Initialize your Next.js project
We will create a simple web app that lets you add a favorite quote to the home page, and edit it afterwards. Run the following command in your terminal to create a new Next.js
project:
Now, navigate to the project directory and install the required dependencies:
We use the @neondatabase/serverless
package as the Postgres client, and drizzle-orm
, a lightweight typescript ORM, to interact with the database. We also use dotenv
to manage environment variables and the drizzle-kit
CLI tool for generating database migrations. For authentication, we'll use the auth.js
library (aliased as v5 of the next-auth
package), which provides a simple way to add authentication to Next.js applications. It comes with built-in support for Okta.
Also, add a .env.local
file to the root of your project, which we'll use to store Neon/Okta connection parameters:
Setting up your Neon database
Initialize a new project
- Log in to the Neon console and navigate to the Projects section.
- Select an existing project or click the New Project button to create a new one.
- Choose the desired region and Postgres version for your project, then click Create Project.
Retrieve your Neon database connection string
Navigate to the Connection Details section to find your database connection string. It should look similar to this:
Add this connection string to the .env.local
file in your Next.js project.
Configuring Okta for authentication
Create an Okta application
- Log in to your Okta developer account and navigate to the Applications section. Click the Create App Integration button.
- Select OIDC - OpenID Connect as the sign-in method.
- Select Web Application as the application type and click Next.
- Provide a name for your application, e.g., "Neon Next Guide".
- Set Sign-in redirect URIs to
http://localhost:3000/api/auth/callback/okta
and Sign-out redirect URIs tohttp://localhost:3000
. - Click Save to create the application.
Retrieve your Okta configuration
From the application's General tab, find the Client ID and Client SECRET. Also note down your Okta Issuer URI, which is the first part of your Okta account's URL, e.g., https://dev-12345.okta.com
. If it isn't clear, visit the Security > API section from the sidebar in the console to find the Issuer URI and remove /oauth2/default
from the end.
Add these as environment variables to the .env.local
file in your Next.js project:
The last variable, AUTH_SECRET
, is a random string used by Auth.js
to encrypt tokens. Run the following command to generate one and add it to your .env.local
file:
note
If you set up an Okta organization account specifically for this guide, you might need to assign yourself to the created Okta application to test the authentication flow. Visit Applications > Applications from the sidebar and select the application you created. In the Assignments tab, click Assign and select your own user account.
Implementing the application
Define database connection and schema
Create a db
folder inside the app/
directory. This is where we'll define the database schema and connection code.
Now, add the file app/db/index.ts
with the following content:
This exports a db
instance that we can use to execute queries against the Neon database.
Next, create a schema.ts
file inside the app/db
directory to define the database schema:
This schema defines a table user_messages
to store a message for each user, with the user_id
provided by Auth0 as the primary key.
Generate and run migrations
We'll use the drizzle-kit
CLI tool to generate migrations for the schema we defined. To configure how it connects to the database, add a drizzle.config.ts
file at the project root.
Now, generate the migration files by running the following command:
This will create a drizzle
folder at the project root with the migration files. To apply the migration to the database, run:
The user_messages
table will now be visible in the Neon console.
Configure Okta authentication
Create a new file auth.ts
in the root directory of the project and add the following content:
This file initializes Auth.js
with Okta as the authentication provider. It also defines a callback to set the sub
claim from the Okta token as the session user ID.
Implement authentication routes
Create a new dynamic route at app/api/auth/[...nextauth]/route.ts
with the following content:
This route file imports the authentication handlers from the auth.ts
file that handle all auth-related requests — sign-in, sign-out, and redirect after authentication.
The auth
object exported from ./auth.ts
is the universal method we can use to interact with the authentication state in the application. For example, we add a User information bar to the app layout that indicates the current user's name and provides a sign-out button.
Replace the contents of the app/layout.tsx
file with the following:
Add interactivity to the application
Our application has a single page that lets the logged-in user store their favorite quote and display it. We implement Next.js
server actions to handle the form submission and database interaction.
Create a new file at app/actions.ts
with the following content:
The createUserMessage
function inserts a new message into the user_messages
table, while deleteUserMessage
removes the message associated with the current user.
Next, we implement a minimal UI to interact with these functions. Replace the contents of the app/page.tsx
file with the following:
This code implements a form with a single text field that lets the user input a quote, and submit it, whereby the quote is stored in the database and associated with the user's Okta
user ID. If a quote is already stored, it displays the quote and provides a button to delete it.
The user.id
property set on the session object provides the current user's ID, which we use to interact with the database on their behalf. If the user is not authenticated, the page displays a login button instead.
Running the application
To start the application, run the following command:
This will start the Next.js development server. Open your browser and navigate to http://localhost:3000
to see the application in action. When running for the first time, you'll see a Log In
button which will redirect you to the Auth.js
widget, prompting you to sign in with Okta.
Once authenticated, you'll be able to visit the home page, add a quote, and see it displayed.
Conclusion
In this guide, we walked through setting up a simple Next.js application with user authentication using Okta and a Neon Postgres database. We defined a database schema using Drizzle ORM, generated migrations, and interacted with the database to store and retrieve user data.
Next, we can add more routes and features to the application. The auth
method can be used in the Next.js API routes or middleware to protect endpoints that require authentication.
To view and manage the users who authenticated with your application, you can navigate to your Okta admin console and view the Directory > People section in the sidebar.
Source code
You can find the source code for the application described in this guide on GitHub.
Resources
For more information on the tools used in this guide, refer to the following documentation:
Need help?
Join our Discord Server to ask questions or see what others are doing with Neon. Users on paid plans can open a support ticket from the console. For more details, see Getting Support.