- Published on
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
1"Todos_Spa_1": { 2 "ClientId": "Todos_Spa_1", 3 "ClientSecret": "1q2w3e*", 4 "RootUrl": "http://localhost:3000" 5},
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.
1// React Client 2var reactClient = configurationSection["Todos_Spa_1:ClientId"]; 3if (!reactClient.IsNullOrWhiteSpace()) 4{ 5 var webClientRootUrl = configurationSection["Todos_Spa_1:RootUrl"]?.TrimEnd('/'); 6 7 await CreateClientAsync( 8 name: reactClient, 9 scopes: commonScopes, 10 grantTypes: new[] { "client_credentials", "authorization_code" }, 11 secret: (configurationSection["Todos_Spa_1:ClientSecret"] ?? "1q2w3e*").Sha256(), 12 requireClientSecret: false, 13 redirectUri: $"{webClientRootUrl}/authentication/login-callback/identity-server4", 14 postLogoutRedirectUri: $"{webClientRootUrl}", 15 corsOrigins: new[] { webClientRootUrl.RemovePostFix("/") } 16 ); 17}
1.3 Run the migration
Now run the migration to add the client to the DB.
2. Create Next.js App
1yarn create next-app
3. Add next-auth package
1yarn add next-auth
4. Add .env file
1NEXTAUTH_URL=http://localhost:3000 2NEXT_PUBLIC_API_URL=https://localhost:44391 3IdentityServer4_Domain=localhost:44354 4IdentityServer4_CLIENT_ID=Todos_Spa_1 5IdentityServer4_CLIENT_SECRET="1q2w3e*" 6NODE_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
1import NextAuth from "next-auth"; 2import Providers from "next-auth/providers"; 3 4export default NextAuth({ 5 // Configure one or more authentication providers 6 providers: [ 7 Providers.IdentityServer4({ 8 id: "identity-server4", 9 name: "IdentityServer4", 10 scope: "openid profile email Todos offline_access", // Allowed Scopes 11 domain: process.env.IdentityServer4_Domain, 12 clientId: process.env.IdentityServer4_CLIENT_ID, 13 clientSecret: process.env.IdentityServer4_CLIENT_SECRET, 14 }), 15 ], 16 callbacks: { 17 /** 18 * @param {object} session Session object 19 * @param {object} token User object (if using database sessions) 20 * JSON Web Token (if not using database sessions) 21 * @return {object} Session that will be returned to the client 22 */ 23 async session(session, token) { 24 // Add property to session, like an access_token from a provider. 25 session.accessToken = token.accessToken; 26 return session; 27 }, 28 29 async jwt(token, user, account, profile, isNewUser) { 30 // Add access_token to the token right after signin 31 if (account?.accessToken) { 32 token.accessToken = account.accessToken; 33 } 34 return token; 35 }, 36 }, 37});
6. Create login Component
1import React from "react"; 2import { signIn, signOut, useSession } from "next-auth/client"; 3function Login() { 4 const [session, loading] = useSession(); 5 6 return ( 7 <> 8 {!session && ( 9 <> 10 Not signed in <br /> 11 <button onClick={() => signIn("identity-server4")}>Sign in</button> 12 </> 13 )} 14 {session && ( 15 <> 16 Signed in as {session.user.email} <br /> 17 <button onClick={() => signOut()}>Sign out</button> 18 </> 19 )} 20 </> 21 ); 22} 23 24export default Login;
7. Render the login component
Now you can render the login component in any page to trigger the auth.
<Login></Login>