generated from imperial/impaas-template
-
Notifications
You must be signed in to change notification settings - Fork 0
/
auth.config.ts
148 lines (134 loc) · 3.78 KB
/
auth.config.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import prisma from "./lib/db"
import { getDepartment } from "./lib/graph"
import { Prisma, Role } from "@prisma/client"
import { DefaultSession, NextAuthConfig } from "next-auth"
import MicrosoftEntraIDProfile from "next-auth/providers/microsoft-entra-id"
const ALLOWED_ADMINS = process.env.CPP_ALLOWED_ADMINS?.split(",") ?? []
const ALLOWED_DEPARTMENTS = process.env.CPP_ALLOWED_DEPARTMENTS?.split(",") ?? ["Computing"]
declare module "@auth/core/adapters" {
interface AdapterUser {
role?: Role
}
}
declare module "@auth/core/jwt" {
interface JWT extends DefaultJWT {
role: Role
id: string
}
}
declare module "next-auth" {
interface User {
role: Role
}
interface Session {
user: {
role: Role
id: string
} & DefaultSession["user"]
}
interface JWT {
role: Role
id: string
}
}
export default {
providers: [
MicrosoftEntraIDProfile({
clientId: process.env.MS_ENTRA_CLIENT_ID,
clientSecret: process.env.MS_ENTRA_CLIENT_SECRET,
tenantId: process.env.MS_ENTRA_TENANT_ID,
authorization: {
params: {
scope: "offline_access openid profile email User.Read",
},
},
async profile(profile) {
// By default the role is STUDENT unless in admins
const role: Role = ALLOWED_ADMINS.includes(profile.email) ? "ADMIN" : "STUDENT"
// Update role if user already exists
const currentUser = await prisma.user.findUnique({
select: {
role: true,
},
where: {
email: profile.email,
},
})
if (currentUser && currentUser.role !== role) {
await prisma.user.update({
data: {
role: role,
},
where: {
email: profile.email,
},
})
}
const user: Prisma.UserCreateInput = {
id: profile.sub,
role,
name: profile.name,
email: profile.email,
studentProfile:
role === "STUDENT"
? {
create: {
studentShortcode: profile.preferred_username.split("@")[0],
},
}
: undefined,
}
return user
},
}),
],
callbacks: {
authorized: async ({ auth }) => {
// Logged in users are authenticated, otherwise redirect to login page
return !!auth
},
signIn: async ({ account, user, email }) => {
// Admins always have access
// Company users will always exist in the database
// If the role field is not present, it means that user doesn't exist
if (user.role === "ADMIN" || user.role === "COMPANY") {
return true
// if email.verificationRequest is true, it means the user is signing in for the first time
// using magic sign in
// If they are allowed to do that the COMPANY check will have already passed
} else if (!account?.access_token || email?.verificationRequest) {
return false
}
const department = await getDepartment(account?.access_token)
return department && ALLOWED_DEPARTMENTS.includes(department)
},
jwt({ token, user }) {
if (user) {
if (user.role) {
token.role = user.role
}
if (user.id) {
token.id = user.id
}
}
// Clear image
if (token.picture) {
delete token.picture
}
if (token.image) {
delete token.image
}
return token
},
session({ session, token }) {
session.user.role = token.role
session.user.id = token.id
return session
},
},
pages: {
signIn: "/auth/login",
verifyRequest: "/auth/login/partner/success",
error: "/auth/error",
},
} satisfies NextAuthConfig