-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
49b45e1
commit b415a0c
Showing
14 changed files
with
233 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import HTTPErrors from 'http-errors'; | ||
|
||
import { BusinessError } from './base'; | ||
|
||
export class BadAuthentication extends BusinessError { | ||
constructor( | ||
public readonly message: string, | ||
public readonly cause?: string, | ||
) { | ||
super(message, 'BAD_AUTHENTICATION', cause, HTTPErrors.Unauthorized); | ||
} | ||
} | ||
|
||
export class MissingAuthenticationHeaders extends BadAuthentication { | ||
constructor() { | ||
super('Missing authentication headers', 'Missing authentication headers'); | ||
} | ||
} | ||
|
||
export class InvalidCredentials extends BadAuthentication { | ||
constructor(public readonly cause: string) { | ||
super('Bad authentication', cause); | ||
} | ||
} | ||
|
||
export class UserNotFound extends InvalidCredentials { | ||
constructor(public readonly username: string) { | ||
super(`User ${username} not found`); | ||
} | ||
} | ||
|
||
export class IncorrectPassword extends InvalidCredentials { | ||
constructor(public readonly username: string) { | ||
super(`Password for ${username} does not match`); | ||
} | ||
} | ||
|
||
export class JWTInvalid extends InvalidCredentials { | ||
constructor() { | ||
super('JWT token invalid'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export * from './cmd'; | ||
export * from './path'; | ||
export * from './authentication'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import jwt from 'json-web-token'; | ||
|
||
import { config } from 'src/config'; | ||
import { IncorrectPassword, JWTInvalid, UserNotFound } from 'src/errors'; | ||
|
||
const sha256 = async (s: string) => { | ||
const msgBuffer = new TextEncoder().encode(s); | ||
const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer); | ||
const hashArray = Array.from(new Uint8Array(hashBuffer)); | ||
const hashHex = hashArray | ||
.map((b) => b.toString(16).padStart(2, '0')) | ||
.join(''); | ||
return hashHex; | ||
}; | ||
|
||
type JWTPayload = { | ||
username: string; | ||
exp: number; | ||
}; | ||
|
||
export const generateToken = async (username: string, password: string) => { | ||
if (config.tgfs.users[username] === undefined) { | ||
throw new UserNotFound(username); | ||
} | ||
if ((await sha256(config.tgfs.users[username].password)) !== password) { | ||
// the password sent in is sha256 hashed | ||
throw new IncorrectPassword(username); | ||
} | ||
return jwt.encode; | ||
}; | ||
|
||
export const verifyToken = (token: string): Promise<JWTPayload> => { | ||
return new Promise((resolve, reject) => { | ||
const payload = jwt.decode( | ||
config.tgfs.jwt.secret, | ||
token, | ||
(error, payload) => { | ||
if (error) { | ||
reject(new JWTInvalid()); | ||
} | ||
}, | ||
); | ||
if (payload.exp < Date.now()) { | ||
reject(new JWTInvalid()); | ||
} | ||
resolve(payload as JWTPayload); | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,54 @@ | ||
import express from 'express'; | ||
import express, { Request, Response } from 'express'; | ||
|
||
import { BadAuthentication } from 'src/errors'; | ||
import { TechnicalError } from 'src/errors/base'; | ||
|
||
import { generateToken, verifyToken } from './auth'; | ||
import { db } from './db'; | ||
|
||
const app = express(); | ||
|
||
app.use(async (req, res, next) => { | ||
if (req.path === '/login') { | ||
next(); | ||
} | ||
|
||
const token = req.headers['authorization']; | ||
if (token === undefined) { | ||
res.redirect('/'); | ||
} | ||
|
||
try { | ||
await verifyToken(token); | ||
} catch (err) { | ||
res.redirect('/'); | ||
} | ||
}); | ||
|
||
// set cors headers | ||
app.use((req, res, next) => { | ||
res.header('Access-Control-Allow-Origin', '*'); | ||
next(); | ||
}); | ||
|
||
app.post('/login', (req, res) => { | ||
const token = generateToken(req.body.username, req.body.password); | ||
res.setHeader('Set-Cookie', `token=${token}; HttpOnly`); | ||
res.end(); | ||
}); | ||
|
||
app.get('/tasks', (req, res) => { | ||
console.log(db.getTasks()); | ||
console.log(req.headers); | ||
res.send(db.getTasks()); | ||
}); | ||
|
||
app.use((err: Error, req: Request, res: Response, next: () => any) => { | ||
if (err instanceof TechnicalError) { | ||
const error = new err.httpError(err.message); | ||
res.status(error.statusCode).send(error.message); | ||
} else { | ||
res.status(500).send('Internal Server Error'); | ||
} | ||
}); | ||
|
||
export const managerServer = app; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters