Table of contents
Intro
In this post we will see how to create a Identity server Client and configure it to implement authenticate for the Next.js Application.
1. Adding a new client to the IdentityServer
first step is to create a new client for the nextjs application. list of client is available in the appsettings.json
file at DbMigrator
project.
1.1 Add the new json entry
"Todos_Spa_1": {
"ClientId": "Todos_Spa_1",
"ClientSecret": "1q2w3e*",
"RootUrl": "http://localhost:3000"
},
1.2 Update the CreateClientsAsync method
In the Domain
project there is a IdentityServerDataSeedContributor
class which has the CreateClientsAsync
method. This method creates the Identity server clients during the migrations. so we will update this method to include the new json entry.
// React Client
var reactClient = configurationSection["Todos_Spa_1:ClientId"];
if (!reactClient.IsNullOrWhiteSpace())
{
var webClientRootUrl = configurationSection["Todos_Spa_1:RootUrl"]?.TrimEnd('/');
await CreateClientAsync(
name: reactClient,
scopes: commonScopes,
grantTypes: new[] { "client_credentials", "authorization_code" },
secret: (configurationSection["Todos_Spa_1:ClientSecret"] ?? "1q2w3e*").Sha256(),
requireClientSecret: false,
redirectUri: $"{webClientRootUrl}/authentication/login-callback/identity-server4",
postLogoutRedirectUri: $"{webClientRootUrl}",
corsOrigins: new[] { webClientRootUrl.RemovePostFix("/") }
);
}
1.3 Run the migration
Now run the migration to add the client to the DB.
2. Create Next.js App
yarn create next-app
3. Add next-auth package
yarn add next-auth
4. Add .env file
NEXTAUTH_URL=http://localhost:3000
NEXT_PUBLIC_API_URL=https://localhost:44391
IdentityServer4_Domain=localhost:44354
IdentityServer4_CLIENT_ID=Todos_Spa_1
IdentityServer4_CLIENT_SECRET="1q2w3e*"
NODE_TLS_REJECT_UNAUTHORIZED=0
NEXT_PUBLIC_API_URL
is the ABP application url.
NEXTAUTH_URL
is the nextjs app url.
NODE_TLS_REJECT_UNAUTHORIZED
is set to 0 to work with ssl in localhost.
5. Setup next-auth
create a /pages/api/auth/[...nextauth].js
and add the following
import NextAuth from "next-auth";
import Providers from "next-auth/providers";
export default NextAuth({
// Configure one or more authentication providers
providers: [
Providers.IdentityServer4({
id: "identity-server4",
name: "IdentityServer4",
scope: "openid profile email Todos offline_access", // Allowed Scopes
domain: process.env.IdentityServer4_Domain,
clientId: process.env.IdentityServer4_CLIENT_ID,
clientSecret: process.env.IdentityServer4_CLIENT_SECRET,
}),
],
callbacks: {
/**
* @param {object} session Session object
* @param {object} token User object (if using database sessions)
* JSON Web Token (if not using database sessions)
* @return {object} Session that will be returned to the client
*/
async session(session, token) {
// Add property to session, like an access_token from a provider.
session.accessToken = token.accessToken;
return session;
},
async jwt(token, user, account, profile, isNewUser) {
// Add access_token to the token right after signin
if (account?.accessToken) {
token.accessToken = account.accessToken;
}
return token;
},
},
});
6. Create login Component
import React from "react";
import { signIn, signOut, useSession } from "next-auth/client";
function Login() {
const [session, loading] = useSession();
return (
<>
{!session && (
<>
Not signed in <br />
<button onClick={() => signIn("identity-server4")}>Sign in</button>
</>
)}
{session && (
<>
Signed in as {session.user.email} <br />
<button onClick={() => signOut()}>Sign out</button>
</>
)}
</>
);
}
export default Login;
7. Render the login component
Now you can render the login component in any page to trigger the auth.
<Login></Login>