DEV Community

Cress
Cress

Posted on

Create a web application for a small business by Next.js with Slack authentication

Creating a web application, it is hard work that implementing a login authentication. Login authentication, reissuance forgotten password, password change and etc. are required. But using NextAuth.js and Slack, you don't need for preparing these yourself. It is very easy and recommended for small businesses.

Create LOCAL server with HTTPS enabled

Slack requires that the application URL uses HTTPS, even for local development. In this case, local-ssl-proxy is easy and useful.

See also:

https://dev.to/cress/when-you-need-https-on-local-environment-local-ssl-proxy-is-the-best-solution-24n6

Configure on Slack side

Follow quickstart.

https://api.slack.com/authentication/quickstart

Create a client ID and a client secret

  1. Click "Create a new Slack app" button.
  2. In "Your Apps" page, click "Create New App" and choose "From scratch"
  3. Enter your app name and pick a workspace to develop your app in.
  4. Click "Create App" button.

Then, in "App Credentials" section of "Basic Information" page, you can see its client ID and client secret.

Configure a redirect URL

  1. In "Add features and functionality" section of "Basic Information" page, click "Permissions".
  2. In Redirect URLs of "OAuth & Permissions" page, click "Add New Redirect URL" button.
  3. Enter "https://localhost:3001" and click "Add" button.
  4. Click "Save URLs" button.

Then you can use authentication by Slack.

Create your application

See also:

https://next-auth.js.org/

As an example, create application named slack-auth-example by create-next-app.

npx create-next-app slack-auth-example
Enter fullscreen mode Exit fullscreen mode

Then, install packages from npm.

npm install next-auth bootstrap react-bootstrap
Enter fullscreen mode Exit fullscreen mode

.env.development.local

Put information depending your environment into .env.development.local file as below:

SLACK_CLIENT_ID = "<Your client ID>"
SLACK_CLIENT_SECRET = "<Your client secret>"
NEXTAUTH_URL = "https://localhost:3001"
NEXTAUTH_SECRET = "changeit"
Enter fullscreen mode Exit fullscreen mode

Values for SLACK_CLIENT_ID and SLACK_CLIENT_SECRET are what you get in "Create a client ID and a client secret" section.

/api/auth/[...nextauth].ts

This is the minimal configuration.

import NextAuth from "next-auth/next"
import SlackProvider from "next-auth/providers/slack"

export const authOptions = {
  providers: [
    SlackProvider({
      clientId: <string>process.env.SLACK_CLIENT_ID,
      clientSecret: <string>process.env.SLACK_CLIENT_SECRET
    })
  ]
}

export default NextAuth(authOptions)
Enter fullscreen mode Exit fullscreen mode

pages/_app.tsx

Surround Component with SessionProvider.

import '@/styles/globals.css'
import { SessionProvider } from 'next-auth/react'
import type { AppProps } from 'next/app'

export default function App({ Component, pageProps: { session, ...pageProps } }: AppProps) {
  return (
    <SessionProvider session={session}>
      <Component {...pageProps} />
    </SessionProvider>
  )
}
Enter fullscreen mode Exit fullscreen mode

Example: index.tsx

It shows login button. As you logged in, it shows your name and logout button.

import React from "react"
import { signIn, signOut, useSession } from "next-auth/react"
import { Button } from "react-bootstrap"
import "bootstrap/dist/css/bootstrap.min.css"

export default function Home() {
  const {data: session, status} = useSession()

  if (status === "loading") {
    return <p>Loading...</p>
  }

  if (status === "authenticated") {
    return (
      <>
        <p>You are logged in as {session.user?.name}</p>
        <Button onClick={() => signOut()}>Logout</Button>
      </>
    )
  } else {
    return (
      <Button onClick={() => signIn("slack")}>Login</Button>
    )
  }
}
Enter fullscreen mode Exit fullscreen mode

Integration with Prisma

NextAuth.js has an adapter for using Prisma. Sessions can be managed in databases.

https://authjs.dev/reference/adapter/prisma

Installation

npm install next-auth @prisma/client @next-auth/prisma-adapter
npm install -D prisma
Enter fullscreen mode Exit fullscreen mode

Prisma setup

An example using MySQL is shown.

npx prisma init --datasource-provider mysql
Enter fullscreen mode Exit fullscreen mode

Then, edit prisma.schema file as below:

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "mys"
  url      = env("DATABASE_URL")
}

model Account {
  id                 String  @id @default(cuid())
  userId             String
  type               String
  provider           String
  providerAccountId  String
  ok                 Boolean?
  refresh_token      String?  @db.Text
  access_token       String?  @db.Text
  expires_at         Int?
  token_type         String?
  scope              String?
  id_token           String?  @db.Text
  state              String?
  session_state      String?

  user User @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([provider, providerAccountId])
}

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

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

model VerificationToken {
  identifier String
  token      String   @unique
  expires    DateTime

  @@unique([identifier, token])
}
Enter fullscreen mode Exit fullscreen mode

Edit following line in .env.development.local file according to your environment.

DATABASE_URL="mysql://johndoe:randompassword@localhost:3306/mydb"
Enter fullscreen mode Exit fullscreen mode

Run a command as below:

npx prisma generate
Enter fullscreen mode Exit fullscreen mode

Now Prisma client has been generated.

/api/auth/[...nextauth].ts

Add adapter property to authOptions.

import { PrismaAdapter } from "@next-auth/prisma-adapter"
import { PrismaClient } from "@prisma/client"
import NextAuth from "next-auth/next"
import SlackProvider from "next-auth/providers/slack"

const prisma = new PrismaClient()

export const authOptions = {
  adapter: PrismaAdapter(prisma),
  providers: [
    SlackProvider({
      clientId: <string>process.env.SLACK_CLIENT_ID,
      clientSecret: <string>process.env.SLACK_CLIENT_SECRET
    })
  ]
}

export default NextAuth(authOptions)
Enter fullscreen mode Exit fullscreen mode

Initialize database

npx prisma migrate dev --name init
Enter fullscreen mode Exit fullscreen mode

For your information

Don't worry that outsiders can't log in even if they have an other domain Slack account. Because the client ID you got is tied to your Slack domain, only your Slack domain member can log in. It is not always necessary to hold user information in your database.

Top comments (0)