Exercise: Social Logins
by Tomas Trescak· Authentication and Authorisation

0 / 1750 XP
The external project has not been reviewed yet
Please follow instructions below to submit your project

It is time to set up your assignment. Here, we will use the information from the previous two chapters to set-up your applications database and authentication.

💼 Assignment Download

You can use code from your tutorial assignment or use the lecture repository below

https://github.com/WesternSydneyUniversity/comp3036-lecture-nextjs

📦 Package Installation

First, we need to install the necessary package; we are going to use the latest version 5 (which is currently in beta). 

In the /apps/admin directory, run the following command:

pnpm add next-auth@beta

Next, we need to generate the secret that next-auth package uses. Run, the following command:

pnpx auth secret

In the next step, we will have to register the generated environment variable to the environment configuration.

🌳 Environment Variables

In the packages/env, we need to set up our environmental variables for safe use. The login process will require five secrets:

  • one for package use:AUTH_SECRET.
  • two for Google login: GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET.
  • and two for GitHub login: GITHUB_CLIENT_ID,GITHUB_CLIENT_SECRET

Adding the specification of these variables in this package will allow the system to check for missing variables upon deployment. Please open the packages/env/admin.ts file and add the following lines:

export const env = createEnv({
  ...
  server: {
    PASSWORD: z.string(),
    JWT_SECRET: z.string(),
    
    // These are new
    DATABASE_URL: z.string().url(),
    AUTH_SECRET: z.string(),
    GITHUB_CLIENT_ID: z.string(),
    GITHUB_CLIENT_SECRET: z.string(),
    GOOGLE_CLIENT_ID: z.string(),
    GOOGLE_CLIENT_SECRET: z.string(),
  },
  ...
  runtimeEnv: {
    PASSWORD: process.env.PASSWORD,
    JWT_SECRET: process.env.JWT_SECRET,
    
    // These are new
    DATABASE_URL: process.env.DATABASE_URL,
    AUTH_SECRET: process.env.AUTH_SECRET
    GITHUB_CLIENT_ID: process.env.GITHUB_CLIENT_ID,
    GITHUB_CLIENT_SECRET: process.env.GITHUB_CLIENT_SECRET,
    GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID,
    GOOGLE_CLIENT_SECRET: process.env.GOOGLE_CLIENT_SECRET,
  },
  ...
});

If you try to run your admin project now, you will see the following error in your console:

We need to add current values in the .env file to fix this. Please see the two previous sections to see what values need to be filled out.

  1. Open the .env file in your root folder. If you do not have it, please rename .env.example file to .env
  2. Modify the current environment variables providing values from the previous two chapters:
    1. DATABASE_URL  (use your connection string to connect to Vercel database or local database)
    2. GITHUB_CLIENT_ID 
    3. GITHUB_CLIENT_SECRET 
    4. GOOGLE_CLIENT_ID 
    5. GOOGLE_CLIENT_SECRET 
  3. You also need to generate a secret for NextAuth package. You can use this website to generate one at least 10 characters long.
  4. Fill out the last compulsory variable:
    1. AUTH_SECRET (copy the value from .env.local file and delete that file afterwards)

Your .env file should look similar to the following (replace `xxxxx` with your values):

PASSWORD=xxxxx
JWT_SECRET=xxxxx
AUTH_SECRET=xxxxx
DATABASE_URL="file:./dev.db"
GITHUB_CLIENT_ID=xxxxx
GITHUB_CLIENT_SECRET=xxxxx
GOOGLE_CLIENT_ID=xxxxx
GOOGLE_CLIENT_SECRET=xxxxx

Try running pnpm dev and your application should now start!

🛡️Database Setup

We need to prepare the user model and create a new task model to handle the application data. Please open schema.prisma file in your opened project and modify the User model to look as the following:

model Account {
    id                String  @id @default(cuid())
    userId            String
    type              String
    provider          String
    providerAccountId String
    refresh_token     String? // @db.Text
    access_token      String? // @db.Text
    expires_at        Int?
    token_type        String?
    scope             String?
    id_token          String? // @db.Text
    session_state     String?
    user              User    @relation(fields: [userId], references: [id], onDelete: Cascade)
    @@unique([provider, providerAccountId])
}

model Session {
  id           String   @id @default(cuid())
  userId       String
  expires      DateTime
  sessionToken String   @unique
  accessToken  String   @unique
  createdAt    DateTime @default(now())
  updatedAt    DateTime @updatedAt
  user         User     @relation(fields: [userId], references: [id])
}

model User {
  id            String    @id @default(cuid())
  name          String?
  email         String?   @unique
  emailVerified DateTime?
  image         String?
  createdAt     DateTime  @default(now())
  updatedAt     DateTime  @updatedAt
  accounts      Account[]
  sessions      Session[]
}

model VerificationRequest {
  id         String   @id @default(cuid())
  identifier String
  token      String   @unique
  expires    DateTime
  createdAt  DateTime @default(now())
  updatedAt  DateTime @updatedAt
  @@unique([identifier, token])
}

Once you are done, you are ready to load these changes to your database. Please run the following command in the terminal in your project folder:

pnpm prisma db push

or 

pnpm prisma migrate dev --name add_aurhentication

In the terminal window, you should see the following message: “Your database is now in sync with your schema.” 

Could you try opening your database in a database client to see these changes? Database clients are visual tools that allow you to see your data, manipulate it, and administer your whole database server.  Concerning database clients, there are many options, let's mention a few:

  1. Your project comes with pre-configured web interface for viewing DB contents. Please run pnpm db:studio in your terminal, which opens a website with your database
  2. JetBrains DataGrip (is free for students)
  3. pgAdmin (free, industry standard)
  4. TablePlus (my favourite, but paid 😞)
  5. DBeaver (has community version)

Whichever option you choose is up to you, but have one database client ready to check out your data at any time! Let's get set up our client to use Prisma!

Next Auth Providers

It is time to tell your application that you will be using “Github” and “Google” as your authentication providers. In the apps/admin package, please create the src/server/auth.ts file. We have to add this provider to the list of providers. find the “providers” key in your authOptions and add the following setup code (or just search for “…add providers here”):

import GoogleProvider from 'next-auth/providers/google';
import GitHubProvider from 'next-auth/providers/github';

import NextAuth from "next-auth"
 
export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [
    GitHubProvider({
      clientId: env.GITHUB_CLIENT_ID,
      clientSecret: env.GITHUB_CLIENT_SECRET
    }),
    GoogleProvider({
     clientId: process.env.GOOGLE_ID,
     clientSecret: process.env.GOOGLE_SECRET,
    }),
  ],
  session: {
    strategy: 'jwt',
  },
})

Next, create the authentication route at /app/api/auth/[...nextauth]/route.ts:

import { handlers } from "@/server/auth" // Referring to the auth.ts we just created
export const { GET, POST } = handlers

You can also create a middleware to keep the session alive in the file src/middleare.ts

export { auth as middleware } from "@/auth"

And done! You just saved yourself about a month of work and a lot of headaches!

🧪 Testing

In the apps/admin create a new sign-in page at src/app/signin/page.tsx with the following code:

import { signIn } from "@/server/auth"
 
export default function Page() {
  return (
    <form
      action={async () => {
        "use server"
        await signIn()
      }}
    >
      <button type="submit">Sign in</button>
    </form>
  )
}

Now:

  1. Run pnpm dev again (if not running already
  2. Woo hoo! application runs 💃🏾
  3. Open the http://localhost:3000/signinClick on “Sign In”
  4. This open as new window with a big “Github” button in the centre. Click on it!
  5. Use your Github login credentials to log in.
  6. 💰 Profit! You should be now logged in and you name should be displayed in the top right corner.

 

Discuss with Others
Ask questions, share your thoughts, and discuss with other learners

Join the discussion to ask questions, share your thoughts, and discuss with other learners
Setup
React Fundamentals
10 points
Next.js
10 points
Advanced React
Databases
10 points
React Hooks
Authentication and Authorisation
10 points
APIs
CI/CD and DevOps
Testing React
Advanced Topics