forked from finos/git-proxy
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathauth.js
More file actions
205 lines (187 loc) · 6.11 KB
/
auth.js
File metadata and controls
205 lines (187 loc) · 6.11 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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
const express = require('express');
const router = new express.Router();
const passport = require('../passport').getPassport();
const { getAuthMethods } = require('../../config');
const passportLocal = require('../passport/local');
const passportAD = require('../passport/activeDirectory');
const authStrategies = require('../passport').authStrategies;
const db = require('../../db');
const { toPublicUser } = require('./publicApi');
const { GIT_PROXY_UI_HOST: uiHost = 'http://localhost', GIT_PROXY_UI_PORT: uiPort = 3000 } =
process.env;
router.get('/', (req, res) => {
res.status(200).json({
login: {
action: 'post',
uri: '/api/auth/login',
},
profile: {
action: 'get',
uri: '/api/auth/profile',
},
logout: {
action: 'post',
uri: '/api/auth/logout',
},
});
});
// login strategies that will work with /login e.g. take username and password
const appropriateLoginStrategies = [passportLocal.type, passportAD.type];
// getLoginStrategy fetches the enabled auth methods and identifies if there's an appropriate
// auth method for username and password login. If there isn't it returns null, if there is it
// returns the first.
const getLoginStrategy = () => {
// returns only enabled auth methods
// returns at least one enabled auth method
const enabledAppropriateLoginStrategies = getAuthMethods().filter((am) =>
appropriateLoginStrategies.includes(am.type.toLowerCase()),
);
// for where no login strategies which work for /login are enabled
// just return null
if (enabledAppropriateLoginStrategies.length === 0) {
return null;
}
// return the first enabled auth method
return enabledAppropriateLoginStrategies[0].type.toLowerCase();
};
const loginSuccessHandler = () => async (req, res) => {
try {
const currentUser = { ...req.user };
delete currentUser.password;
console.log(
`serivce.routes.auth.login: user logged in, username=${
currentUser.username
} profile=${JSON.stringify(currentUser)}`,
);
res.send({
message: 'success',
user: toPublicUser(currentUser),
});
} catch (e) {
console.log(`service.routes.auth.login: Error logging user in ${JSON.stringify(e)}`);
res.status(500).send('Failed to login').end();
}
};
// TODO: provide separate auth endpoints for each auth strategy or chain compatibile auth strategies
// TODO: if providing separate auth methods, inform the frontend so it has relevant UI elements and appropriate client-side behavior
router.post(
'/login',
(req, res, next) => {
const authType = getLoginStrategy();
if (authType === null) {
res.status(403).send('Username and Password based Login is not enabled at this time').end();
return;
}
console.log('going to auth with', authType);
return passport.authenticate(authType)(req, res, next);
},
loginSuccessHandler(),
);
router.get('/oidc', passport.authenticate(authStrategies['openidconnect'].type));
router.get('/oidc/callback', (req, res, next) => {
passport.authenticate(authStrategies['openidconnect'].type, (err, user, info) => {
if (err) {
console.error('Authentication error:', err);
return res.status(401).end();
}
if (!user) {
console.error('No user found:', info);
return res.status(401).end();
}
req.logIn(user, (err) => {
if (err) {
console.error('Login error:', err);
return res.status(401).end();
}
console.log('Logged in successfully. User:', user);
return res.redirect(`${uiHost}:${uiPort}/dashboard/profile`);
});
})(req, res, next);
});
router.post('/logout', (req, res, next) => {
req.logout(req.user, (err) => {
if (err) return next(err);
});
res.clearCookie('connect.sid');
res.send({ isAuth: req.isAuthenticated(), user: req.user });
});
router.get('/profile', async (req, res) => {
if (req.user) {
const userVal = await db.findUser(req.user.username);
res.send(toPublicUser(userVal));
} else {
res.status(401).end();
}
});
router.post('/gitAccount', async (req, res) => {
if (req.user) {
try {
let username =
req.body.username == null || req.body.username == 'undefined'
? req.body.id
: req.body.username;
username = username?.split('@')[0];
if (!username) {
res.status(400).send('Error: Missing username. Git account not updated').end();
return;
}
const reqUser = await db.findUser(req.user.username);
if (username !== reqUser.username && !reqUser.admin) {
res.status(403).send('Error: You must be an admin to update a different account').end();
return;
}
const user = await db.findUser(username);
console.log('Adding gitAccount' + req.body.gitAccount);
user.gitAccount = req.body.gitAccount;
db.updateUser(user);
res.status(200).end();
} catch (e) {
res
.status(500)
.send({
message: `Error updating git account: ${e.message}`,
})
.end();
}
} else {
res.status(401).end();
}
});
router.get('/me', async (req, res) => {
if (req.user) {
const userVal = await db.findUser(req.user.username);
res.send(toPublicUser(userVal));
} else {
res.status(401).end();
}
});
router.post('/create-user', async (req, res) => {
if (!req.user || !req.user.admin) {
return res.status(401).send({
message: 'You are not authorized to perform this action...',
});
}
try {
const { username, password, email, gitAccount, admin: isAdmin = false } = req.body;
if (!username || !password || !email || !gitAccount) {
return res.status(400).send({
message: 'Missing required fields: username, password, email, and gitAccount are required',
});
}
await db.createUser(username, password, email, gitAccount, isAdmin);
res.status(201).send({
message: 'User created successfully',
username,
});
} catch (error) {
console.error('Error creating user:', error);
res.status(400).send({
message: error.message || 'Failed to create user',
});
}
});
module.exports = router;
module.exports = {
router,
loginSuccessHandler,
};