-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.cjs
152 lines (125 loc) · 4.31 KB
/
server.cjs
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
149
150
151
152
"use strict";
const Hapi = require("@hapi/hapi");
const Jwt = require("@hapi/jwt");
const Cookie = require("@hapi/cookie");
const mongoose = require("mongoose");
const routes = require("./routes/index.cjs");
const errorController = require("./controllers/error-controller.cjs");
const User = require("./models/user.cjs");
// Read .env file
require("dotenv").config();
const init = async () => {
const server = Hapi.server({
port: process.env.HAPI_PORT || 8001,
host: process.env.HAPI_HOST || "localhost",
routes: {
cors: {
origin: ["*"],
},
},
});
/////////////////////////////////////////////////////
// Authentication and authorization
await server.register([Jwt, Cookie]);
// Handle bearer token stored in the request header
// By default, hapi check the jwt token in the authentication header
// verify: This object contains options for verifying the JWT token.
// aud: The "audience" claim to verify. If set to false, the audience claim will not be verified.
// iss: The "issuer" claim to verify. If set to false, the issuer claim will not be verified.
// sub: The "subject" claim to verify. If set to false, the subject claim will not be verified.
// nbf: If true, the "not before" claim will be verified.
// exp: If true, the "expiration" claim will be verified.
// maxAgeSec: Maximum allowed age for the token in seconds. Tokens older than this will be rejected.
// timeSkewSec: Allowed clock skew for verifying the token's expiration time, in seconds.
server.auth.strategy("jwt-bearer", "jwt", {
keys: process.env.JWT_SECRET,
verify: {
aud: false,
iss: false,
sub: false,
nbf: true,
exp: true,
// maxAgeSec: 14400, // this only allow the token to be 4 hours old but the token set in this project is 90 days old so if this turn on then the bearer validation will always be fail even if the token is valid and not expired
// timeSkewSec: 15,
},
validate: async (artifacts, req, h) => {
try {
const currentUser = await User.findById(artifacts.decoded.payload.id);
// If the user have disabled the account (active === false) then we will not allow them to access the account with the current session token
if (!currentUser) {
return {
isValid: false,
};
}
return {
isValid: true,
credential: {
user: artifacts.decoded.payload,
},
};
} catch (err) {
return {
isValid: false,
};
}
},
});
// Handle jwt token stored in the cookie
server.auth.strategy("jwt-cookie", "cookie", {
cookie: {
name: "jwt_cookie",
password: process.env.JWT_SECRET,
isSecure: process.env.NODE_ENV === "production",
isHttpOnly: true,
isSameSite: "Lax",
ttl: process.env.JWT_COOKIE_EXPIRES_IN * 1 * 60 * 60 * 24 * 1000,
},
validate: async (req, session) => {
try {
// session will contain the jwt token stored in the cookie
const decoded = Jwt.token.decode(session);
// // Find the corresponding user in the session
// If the user have disabled the account (active === false) then we will not allow them to access the account with the current session token
const currentUser = await User.findById(decoded.decoded.payload.id);
if (!currentUser) {
return {
isValid: false,
};
}
return {
isValid: true,
credentials: {
user: decoded.decoded.payload,
},
};
} catch (err) {
return {
isValid: false,
};
}
},
});
// Set the default authentication to cookie
server.auth.default("jwt-cookie");
//////////////////////////////////////////////////////////////
// Define route here
server.route(routes);
// Handle global error
errorController(server);
await server.start();
console.log(
`Server running on port ${process.env.HAPI_PORT || 3000}: `,
server.info.uri
);
// Handle unknown error
process.on("unhandledRejection", (error) => {
console.log(error);
process.exit(1);
});
};
// Connect to mongodb
mongoose.connect(process.env.MONGODB_URI).then(() => {
console.log("MongoDB connect successfully!");
});
// Start the server
init();