-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauth.ts
More file actions
154 lines (142 loc) · 4.68 KB
/
auth.ts
File metadata and controls
154 lines (142 loc) · 4.68 KB
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
153
154
import passport from "passport";
import passportLocal from "passport-local";
import {Express, NextFunction, Request, Response} from "express";
import {ErrorCause, SimpleError} from "./error";
import session from 'express-session';
export class User {
private readonly _username: string;
constructor(username: string) {
this._username = username;
}
get username(): string {
return this._username;
}
}
/**
* Retrieve the user from the current request's session.
* @param req HTTP request.
*/
export function getUser(req: any):User {
return new User(req.session?.passport?.user);
}
/**
* Apply authentication's routes on the Express Application
* @param APP Express Application
*/
export function applyAuth(APP: Express) {
// create a new express session to manage user session
// and send cookie session to the client to maintain the login session.
APP.use(session({
secret: process.env.SESSION_SECRET || 'secure_me',
resave: false,
saveUninitialized: false,
cookie: {
secure: process.env.HTTPS?.toLowerCase() === "true", // HTTPS only
httpOnly: true, // Prevent XSS attacks
maxAge: 4 * 60 * 60 * 1000 // set expires time in milliseconds: 4 hours
}
}))
.use(passport.initialize())
.use(passport.session())
/* Request body should be like :
{
"username":"john",
"password":"P455w0rd"
}
*/
.post('/login', authenticate, (req: Request, res: Response) => {
res.send({
message: 'Logged In Successful',
username: getUser(req).username
})
})
.post('/logout', function (req: Request, res: Response, next: NextFunction) {
req.logout(function (err: Error) {
if (err) {
return next(err);
}
res.send({
message: 'Logged Out Successful'
})
});
})
// TODO : Return User Information
.get('/secret', ensureAuthenticated, function (req: Request, res: Response, next: NextFunction) {
res.send({
username: getUser(req).username
})
});
}
/**
* Verify that the user is correctly authenticated.
*
* @param req The HTTP request.
* @param res The HTTP response.
* @param next The next function to call the next middleware.
*/
export const ensureAuthenticated = (req: Request, res: Response, next: CallableFunction) => {
try {
if (req.isAuthenticated()) {
// If the user is authenticated, continue to the next middleware
next();
} else {
// Send a not connected response to the client.
new SimpleError('You must be logged in to see this page.', ErrorCause.NOT_CONNECTED).send(res);
}
} catch (e) {
next(e);
}
};
/**
* Retrieve the local user by unique email and then
* compare given hashed password with the hashed database password.
*/
passport.use('login',
new passportLocal.Strategy(
async function (username, password, done) {
try {
// TODO : Make identification with an external service. (By example a Database, or another API).
// It could help to retrieve more information about the user.
if (password === process.env.AUTH_PASSWORD && username === process.env.AUTH_USERNAME) {
// Log In Successfully
return done(null, new User(username));
}
// Bad credentials
return done(null, false);
} catch (err) {
// Something wrong !
return done(err);
}
}
));
const authenticate = (req: Request, res: Response, next: CallableFunction) => {
passport.authenticate('login', (err: Error, user: any, _: CallableFunction) => {
if (err) {
return next(err);
}
if (!user) { // Login Strategy returned done(null, false)
new SimpleError('Bad credentials', ErrorCause.BAD_CREDENTIALS).send(res)
}
req.logIn(user, (err) => {
if (err) {
return next(err);
}
return next();
});
})(req, res, next);
};
/**
* Indicate what to save in the session.
* Only the user mail is saved when a session is created.
*/
passport.serializeUser(function (user: any, done) {
if (user) {
done(null, user.username);
}
});
/**
* Indicate how to retrieve the user's data
*/
passport.deserializeUser(function (username: string, done) {
done(null, new User(username));
});