-
Notifications
You must be signed in to change notification settings - Fork 0
/
middleware.ts
95 lines (78 loc) · 2.61 KB
/
middleware.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
/**
* This files purpose is to decode the incoming JWT from users to ensure validity.
* Once decoded, the id of the user can be extracted from the payload section and
* used.
*
* https://nextjs.org/docs/advanced-features/middleware
*/
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { verify } from './lib/jwt'
import { USER_COOKIE_NAME } from './lib/util'
import { User } from './pages/api/auth/login'
import { VOTER_TYPE_ID } from './prisma/types'
export const USER_ID_HEADER_NAME = 'user-id'
// https://levelup.gitconnected.com/how-to-add-jwt-authentication-to-nextjs-apps-a0dc83bd257d
// How to use a cookie to have user information on every request
export async function middleware(request: NextRequest) {
/*
Implementation based off key concepts here:
- https://github.com/vercel/next.js/pull/41380
- https://levelup.gitconnected.com/how-to-add-jwt-authentication-to-nextjs-apps-a0dc83bd257d
*/
// Ensure cookie is present
if (!request.cookies.has(USER_COOKIE_NAME)) {
return NextResponse.next({
status: 400,
statusText: 'Missing Cookie! This is needed for authentification purposes, try closing your browser and logging in again.'
})
}
const user = JSON.parse(request.cookies.get(USER_COOKIE_NAME).value) as User
// Check parse success and if logged in is true
if (!user?.isLoggedIn) {
return NextResponse.next({
status: 400,
statusText: 'Cookie parse failed or you are not logged in!'
})
}
// Redirect voters trying to access the employee endpoints
if (user.role === VOTER_TYPE_ID && request.url.includes('employee')) {
const url = request.nextUrl.clone()
url.pathname = '/'
return NextResponse.rewrite(url)
}
// Parse the api key using our server's secret
const token = await verify(user.apiKey, process.env.JWT_PRIVATE_KEY) as { id: number, exp: number }
// Ensure token parsed
if (!token) {
return NextResponse.next({
status: 403,
statusText: 'Bearer token parse failed.'
})
}
// Clone request headers
const headers = new Headers(request.headers);
// Add a new request header
headers.append(USER_ID_HEADER_NAME, `${token.id}`)
const res = NextResponse.next({
// New option `request.headers` which accepts a Headers object
// overrides request headers with the specified new ones.
request: {
headers
}
});
return res
}
/**
* Middleware shall run on the routes listed below:
*/
export const config = {
matcher: [
'/api/course',
'/api/acquisition',
'/api/login',
'/api/user',
'/courses',
'/accounts'
]
}