mirror of
https://github.com/PhoenixTwoFive/karaoqueue.git
synced 2025-05-19 11:01:47 +02:00
Add authentication and authorization
This commit is contained in:
parent
60dfea50c4
commit
b28dbba746
@ -5,7 +5,7 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node dist/index.js",
|
"start": "node dist/index.js",
|
||||||
"debug": "node --nolazy --inspect-brk=9229 dist/index.js",
|
"debug": "node --nolazy dist/index.js",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
|
@ -1,11 +1,29 @@
|
|||||||
|
import { Request, Response } from "express";
|
||||||
import { Post, BodyParam, Body, Res, Req, JsonController, UseBefore, Get, CookieParam } from "routing-controllers";
|
import { Post, BodyParam, Body, Res, Req, JsonController, UseBefore, Get, CookieParam } from "routing-controllers";
|
||||||
import { UserCredential } from "../models/usercredential.model";
|
import User from "../interfaces/user.interface";
|
||||||
|
import { JwtMiddleware } from "../middleware/jwt.middleware";
|
||||||
|
|
||||||
@JsonController("/auth")
|
@JsonController("/auth")
|
||||||
export class AuthenticationController {
|
export class AuthenticationController {
|
||||||
|
|
||||||
@Post("/login")
|
@Post("/login")
|
||||||
doLogin(@Body() usercredential: UserCredential, @Res() res: any) {
|
doLogin(@Body() user: User, @Res() res: Response) {
|
||||||
return "//TODO login";
|
if (user.username === process.env.KQUEUE_USERNAME) {
|
||||||
|
if (user.password === process.env.KQUEUE_PASSWORD) {
|
||||||
|
const jwtMiddleware = new JwtMiddleware();
|
||||||
|
const tokenData = jwtMiddleware.createToken(user);
|
||||||
|
res.cookie("jwt",tokenData,);
|
||||||
|
res.status(200);
|
||||||
|
res.send("Welcome.")
|
||||||
|
return res;
|
||||||
|
} else {
|
||||||
|
// TODO wrong password.
|
||||||
|
return "Wrong password."
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// TODO wrong user.
|
||||||
|
return "Wrong user."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get("/logout")
|
@Get("/logout")
|
||||||
|
11
backend/karaoqueue-backend/src/exceptions/HttpException.ts
Normal file
11
backend/karaoqueue-backend/src/exceptions/HttpException.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
class HttpException extends Error {
|
||||||
|
public status: number;
|
||||||
|
public message: string;
|
||||||
|
constructor(status: number, message: string) {
|
||||||
|
super(message);
|
||||||
|
this.status = status;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HttpException;
|
@ -1,10 +1,12 @@
|
|||||||
import "reflect-metadata";
|
import "reflect-metadata";
|
||||||
import { createExpressServer } from "routing-controllers";
|
import { Request, Response } from "express";
|
||||||
|
import { Action, createExpressServer } from "routing-controllers";
|
||||||
import { QueueController } from "./controllers/queue.controller";
|
import { QueueController } from "./controllers/queue.controller";
|
||||||
import { SongController } from "./controllers/songs.controller";
|
import { SongController } from "./controllers/songs.controller";
|
||||||
import { StatisticsController } from "./controllers/statistics.controller";
|
import { StatisticsController } from "./controllers/statistics.controller";
|
||||||
import { AuthenticationController } from "./controllers/auth.controller";
|
import { AuthenticationController } from "./controllers/auth.controller";
|
||||||
import { RpcController } from "./controllers/rpc.controller";
|
import { RpcController } from "./controllers/rpc.controller";
|
||||||
|
import jwt from "jsonwebtoken";
|
||||||
|
|
||||||
|
|
||||||
import * as dotenv from "dotenv";
|
import * as dotenv from "dotenv";
|
||||||
@ -13,7 +15,34 @@ dotenv.config();
|
|||||||
const app = createExpressServer({
|
const app = createExpressServer({
|
||||||
routePrefix: "/api",
|
routePrefix: "/api",
|
||||||
cors: true,
|
cors: true,
|
||||||
|
authorizationChecker: async (action: Action) => {
|
||||||
|
const req: Request = action.request;
|
||||||
|
const secret = process.env.KQUEUE_JWTSECRET;
|
||||||
|
const token = parseCookies(req.headers.cookie)["jwt"];
|
||||||
|
if (token) {
|
||||||
|
try {
|
||||||
|
const verificationResponse = jwt.verify(token, secret);
|
||||||
|
if (verificationResponse) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
controllers: [QueueController, SongController, StatisticsController, AuthenticationController, RpcController]
|
controllers: [QueueController, SongController, StatisticsController, AuthenticationController, RpcController]
|
||||||
});
|
});
|
||||||
|
app.listen(process.env.KQUEUE_PORT);
|
||||||
|
|
||||||
app.listen(process.env.KQUEUE_PORT);
|
function parseCookies(str) {
|
||||||
|
let rx = /([^;=\s]*)=([^;]*)/g;
|
||||||
|
let obj = {};
|
||||||
|
for (let m; m = rx.exec(str);)
|
||||||
|
obj[m[1]] = decodeURIComponent(m[2]);
|
||||||
|
return obj;
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
interface DataStoredInToken {
|
||||||
|
_id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DataStoredInToken;
|
@ -0,0 +1,6 @@
|
|||||||
|
interface User {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default User;
|
14
backend/karaoqueue-backend/src/middleware/jwt.middleware.ts
Normal file
14
backend/karaoqueue-backend/src/middleware/jwt.middleware.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import DataStoredInToken from "../interfaces/dataStoredInToken.interface";
|
||||||
|
import User from "../interfaces/user.interface";
|
||||||
|
import * as jwt from 'jsonwebtoken';
|
||||||
|
|
||||||
|
export class JwtMiddleware {
|
||||||
|
public createToken(user: User): string {
|
||||||
|
const expiresIn = 60 * 60; // an hour
|
||||||
|
const secret = process.env.KQUEUE_JWTSECRET;
|
||||||
|
const dataStoredInToken: DataStoredInToken = {
|
||||||
|
_id: user.username,
|
||||||
|
};
|
||||||
|
return jwt.sign(dataStoredInToken, secret, { expiresIn });
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +0,0 @@
|
|||||||
export interface UserCredential {
|
|
||||||
username: string,
|
|
||||||
password: string
|
|
||||||
}
|
|
@ -244,12 +244,12 @@ paths:
|
|||||||
'200':
|
'200':
|
||||||
description: >
|
description: >
|
||||||
Successfully authenticated.
|
Successfully authenticated.
|
||||||
The session ID is returned in a cookie named `connect.sid`. You need to include this cookie in subsequent requests.
|
The session ID is returned in a cookie named `jwt`. You need to include this cookie in subsequent requests.
|
||||||
headers:
|
headers:
|
||||||
Set-Cookie:
|
Set-Cookie:
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
example: connect.sid=abcde12345; Path=/; HttpOnly
|
example: jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiJhZG1pbiIsImlhdCI6MTYwMTY1MDYwNSwiZXhwIjoxNjAxNjU0MjA1fQ.uGvOlBAZdbPT8U9s7jEt5PUWyxLrpgaf02EoPVC_Zlsd; Path=/; HttpOnly
|
||||||
/auth/logout:
|
/auth/logout:
|
||||||
get:
|
get:
|
||||||
summary: Logs the user out and invalidates the session on the server
|
summary: Logs the user out and invalidates the session on the server
|
||||||
@ -345,7 +345,7 @@ components:
|
|||||||
cookieAuth: # arbitrary name for the security scheme; will be used in the "security" key later
|
cookieAuth: # arbitrary name for the security scheme; will be used in the "security" key later
|
||||||
type: apiKey
|
type: apiKey
|
||||||
in: cookie
|
in: cookie
|
||||||
name: connect.sid # cookie name
|
name: jwt # cookie name
|
||||||
schemas:
|
schemas:
|
||||||
QueueEntry:
|
QueueEntry:
|
||||||
type: object
|
type: object
|
||||||
|
Loading…
x
Reference in New Issue
Block a user