Enterprise-Level Authentication in a Containerized Environment for Next.js 13 - AuthJS Patch
Table of contents
Recently, I've published a step by step guide on Enterprise-Level Authentication in a Containerized Environment for NextJS and while searching on the internet I saw a post on Keycloak groups. benmarte was having a problem while integrating Keycloak using auth.js instead of next-auth. In this post I'll explain how you can handle authentication using auth.js.
To get the most out of this post please setup your environment as I shared in my previous post.
TL;DR
https://github.com/ozdemirrulass/nextjs-keycloak-authjs
NextJS 13 Keycloak Integration Using AuthJS
- Install AuthJS as it is suggested in official documentation:
npm install next-auth@beta
- Create
.env.local
file in the root directory of your next-app project and add the following:
AUTH_SECRET=secret
NEXT_PUBLIC_KEYCLOAK_REALM=<realm-name>
NEXT_PUBLIC_KEYCLOAK_CLIENT_ID=<client-name>
KEYCLOAK_CLIENT_SECRET=<client-secret-from-keycloak>
NEXT_LOCAL_KEYCLOAK_URL="http://localhost:8080"
NEXT_CONTAINER_KEYCLOAK_ENDPOINT="http://keycloak:8080"
💡
You can use following commands to produce AUTH_SECRET value. This secret is used to sign and encrypt cookies.
💡
You can see where to find other values in my PREVIOUS POST.
openssl rand -base64 33
or
npx auth secret
- Create
/types
folder in your projects root and createnode-env.d.ts
file in it.
// /types/node-env.d.ts
declare namespace NodeJS {
export interface ProcessEnv {
NEXT_PUBLIC_KEYCLOAK_CLIENT_ID: string
KEYCLOAK_CLIENT_SECRET: string
NEXT_LOCAL_KEYCLOAK_URL: string
NEXT_PUBLIC_KEYCLOAK_REALM: string
NEXT_CONTAINER_KEYCLOAK_ENDPOINT: string
}
}
- Create
auth.ts
file under your/src
directory and add the following code:
// /src/auth.ts
import NextAuth from "next-auth"
import Keycloak from "next-auth/providers/keycloak";
export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [
Keycloak({
jwks_endpoint: `${process.env.NEXT_CONTAINER_KEYCLOAK_ENDPOINT}/realms/myrealm/protocol/openid-connect/certs`,
wellKnown: undefined,
clientId: process.env.NEXT_PUBLIC_KEYCLOAK_CLIENT_ID,
clientSecret: process.env.KEYCLOAK_CLIENT_SECRET,
issuer: `${process.env.NEXT_LOCAL_KEYCLOAK_URL}/realms/${process.env.NEXT_PUBLIC_KEYCLOAK_REALM}`,
authorization: {
params: {
scope: "openid email profile",
},
url: `${process.env.NEXT_LOCAL_KEYCLOAK_URL}/realms/myrealm/protocol/openid-connect/auth`,
},
token: `${process.env.NEXT_CONTAINER_KEYCLOAK_ENDPOINT}/realms/myrealm/protocol/openid-connect/token`,
userinfo: `${process.env.NEXT_CONTAINER_KEYCLOAK_ENDPOINT}/realms/myrealm/protocol/openid-connect/userinfo`,
}),
],
});
💡
This part is important! We must use any kind of parameter indicating urls as
localhost
but urls used for sending a request must use container name
for connectivity purposes through docker network.- Now it's time to create our
route.ts
and it must be in/src/app/api/auth/[...nextauth]/route.ts
// /src/app/api/auth/[...nextauth]/route.ts
import { handlers } from "@/auth";
export const { GET, POST } = handlers;
- We are going to need a Sign-In component! Let's create It. Create a
components
folder under your/src
directory and create a file assign-in.tsx
.
// /src/components/sign-in.tsx
import { signIn } from "@/auth"
export function SignIn() {
return (
<form
action={async () => {
"use server"
await signIn("keycloak")
}}
>
<button type="submit">Signin with Keycloak</button>
</form>
)
}
- It's time to replace our
src/app/page.tsx
:
// src/app/page.tsx
import { auth } from "@/auth";
import { SignIn } from "../components/sign-in";
export default async function Home() {
const session = await auth();
if (session) {
return (
<div>
<div>Your name is {session.user?.name}</div>
</div>
);
}
return (
<div>
<SignIn />
</div>
);
}
Congratulations 👏 You've done it. You just implemented an Enterprise-Level Authentication in a Containerized Environment for Next.js 13 using AuthJS instead of NextAuth !
docker compose -f docker-compose.dev.yml build
docker compose -f docker-compose.dev.yml up -d
Thank you and see you soon!