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:
Configure on Slack side
Follow quickstart.
https://api.slack.com/authentication/quickstart
Create a client ID and a client secret
- Click "Create a new Slack app" button.
- In "Your Apps" page, click "Create New App" and choose "From scratch"
- Enter your app name and pick a workspace to develop your app in.
- 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
- In "Add features and functionality" section of "Basic Information" page, click "Permissions".
- In Redirect URLs of "OAuth & Permissions" page, click "Add New Redirect URL" button.
- Enter "https://localhost:3001" and click "Add" button.
- Click "Save URLs" button.
Then you can use authentication by Slack.
Create your application
See also:
As an example, create application named slack-auth-example by create-next-app
.
npx create-next-app slack-auth-example
Then, install packages from npm.
npm install next-auth bootstrap react-bootstrap
.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"
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)
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>
)
}
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>
)
}
}
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
Prisma setup
An example using MySQL is shown.
npx prisma init --datasource-provider mysql
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])
}
Edit following line in .env.development.local
file according to your environment.
DATABASE_URL="mysql://johndoe:randompassword@localhost:3306/mydb"
Run a command as below:
npx prisma generate
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)
Initialize database
npx prisma migrate dev --name init
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)