feat: add Oauth authentication

pull/1/head
Francesco Minnocci 1 year ago
parent 4e417266c4
commit 3d149e0d1c
Signed by: BachoSeven
GPG Key ID: 2BE4AB7FDAD828A4

@ -1,3 +1,3 @@
BASE_URL=/
DATABASE_PATH=db.local.json
DATABASE_PATH=db.local.json

@ -34,6 +34,7 @@
"remark-parse": "^10.0.1",
"remark-rehype": "^10.1.0",
"sass": "^1.55.0",
"simple-oauth2": "^5.0.0",
"unified": "^10.1.2",
"url-pattern": "^1.0.3",
"vite": "^3.2.2"
@ -43,6 +44,7 @@
"@types/express": "^4.17.14",
"@types/morgan": "^1.9.3",
"@types/node": "^18.11.9",
"@types/simple-oauth2": "^4.1.1",
"concurrently": "^7.5.0",
"esbuild": "^0.15.13",
"npm-run-all": "^4.1.5",

@ -7,6 +7,7 @@ specifiers:
'@types/express': ^4.17.14
'@types/morgan': ^1.9.3
'@types/node': ^18.11.9
'@types/simple-oauth2': ^4.1.1
body-parser: ^1.20.1
chalk: ^5.1.2
concurrently: ^7.5.0
@ -27,6 +28,7 @@ specifiers:
remark-parse: ^10.0.1
remark-rehype: ^10.1.0
sass: ^1.55.0
simple-oauth2: ^5.0.0
ts-node: ^10.9.1
typescript: ^4.8.4
unified: ^10.1.2
@ -53,6 +55,7 @@ dependencies:
remark-parse: 10.0.1
remark-rehype: 10.1.0
sass: 1.56.0
simple-oauth2: 5.0.0
unified: 10.1.2
url-pattern: 1.0.3
vite: 3.2.2_sass@1.56.0
@ -62,6 +65,7 @@ devDependencies:
'@types/express': 4.17.14
'@types/morgan': 1.9.3
'@types/node': 18.11.9
'@types/simple-oauth2': 4.1.1
concurrently: 7.5.0
esbuild: 0.15.13
npm-run-all: 4.1.5
@ -337,6 +341,38 @@ packages:
requiresBuild: true
optional: true
/@hapi/boom/10.0.0:
resolution: {integrity: sha512-1YVs9tLHhypBqqinKQRqh7FUERIolarQApO37OWkzD+z6y6USi871Sv746zBPKcIOBuI6g6y4FrwX87mmJ90Gg==}
dependencies:
'@hapi/hoek': 10.0.1
dev: false
/@hapi/bourne/3.0.0:
resolution: {integrity: sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==}
dev: false
/@hapi/hoek/10.0.1:
resolution: {integrity: sha512-CvlW7jmOhWzuqOqiJQ3rQVLMcREh0eel4IBnxDx2FAcK8g7qoJRQK4L1CPBASoCY6y8e6zuCy3f2g+HWdkzcMw==}
dev: false
/@hapi/hoek/9.3.0:
resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==}
dev: false
/@hapi/topo/5.1.0:
resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==}
dependencies:
'@hapi/hoek': 9.3.0
dev: false
/@hapi/wreck/18.0.0:
resolution: {integrity: sha512-Yk9STxoM06Hjjq58cH0KFG91u9F2h9eVE72o8vUr3AfK80qt7I2POG5+cDGTEntbnvvzm0ERow2sjG3QsqCWUA==}
dependencies:
'@hapi/boom': 10.0.0
'@hapi/bourne': 3.0.0
'@hapi/hoek': 10.0.1
dev: false
/@jridgewell/gen-mapping/0.1.1:
resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==}
engines: {node: '>=6.0.0'}
@ -454,6 +490,20 @@ packages:
picomatch: 2.3.1
dev: false
/@sideway/address/4.1.4:
resolution: {integrity: sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==}
dependencies:
'@hapi/hoek': 9.3.0
dev: false
/@sideway/formula/3.0.1:
resolution: {integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==}
dev: false
/@sideway/pinpoint/2.0.0:
resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==}
dev: false
/@tsconfig/node10/1.0.9:
resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==}
dev: true
@ -565,6 +615,10 @@ packages:
'@types/node': 18.11.9
dev: true
/@types/simple-oauth2/4.1.1:
resolution: {integrity: sha512-8jqhfUFb0FoCl2Od4czprB7ubM8/Fuo3tg+vQZ00zYtPcNLogGyDgm2DVfVvD3NYXK7AscKOXSaW33NHUWpNBg==}
dev: true
/@types/unist/2.0.6:
resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==}
dev: false
@ -1630,6 +1684,16 @@ packages:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
dev: true
/joi/17.7.0:
resolution: {integrity: sha512-1/ugc8djfn93rTE3WRKdCzGGt/EtiYKxITMO4Wiv6q5JL1gl9ePt4kBsl1S499nbosspfctIQTpYIhSmHA3WAg==}
dependencies:
'@hapi/hoek': 9.3.0
'@hapi/topo': 5.1.0
'@sideway/address': 4.1.4
'@sideway/formula': 3.0.1
'@sideway/pinpoint': 2.0.0
dev: false
/js-tokens/4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
dev: false
@ -2455,6 +2519,17 @@ packages:
get-intrinsic: 1.1.3
object-inspect: 1.12.2
/simple-oauth2/5.0.0:
resolution: {integrity: sha512-8291lo/z5ZdpmiOFzOs1kF3cxn22bMj5FFH+DNUppLJrpoIlM1QnFiE7KpshHu3J3i21TVcx4yW+gXYjdCKDLQ==}
dependencies:
'@hapi/hoek': 10.0.1
'@hapi/wreck': 18.0.0
debug: 4.3.4
joi: 17.7.0
transitivePeerDependencies:
- supports-color
dev: false
/source-map-js/1.0.2:
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
engines: {node: '>=0.10.0'}

@ -0,0 +1,52 @@
import { Router } from 'express';
import { AuthorizationCode } from 'simple-oauth2'
export function setupOauth(r: Router) {
const config = {
client: {
id: process.env.OAUTH_CLIENT_ID ?? '',
secret: process.env.OAUTH_CLIENT_SECRET ?? '',
},
auth: {
authorizePath: process.env.OAUTH_AUTH_URL ?? '',
tokenHost: process.env.OAUTH_TOKEN_HOST ?? '',
tokenPath: process.env.OAUTH_TOKEN_PATH ?? ''
},
};
const conf = {
redirect_uri: process.env.OAUTH_REDIRECT_URL ?? '',
scope: process.env.OAUTH_SCOPES ?? '',
}
const client = new AuthorizationCode(config);
const authorizationUri = client.authorizeURL({
redirect_uri: conf.redirect_uri,
scope: conf.scope,
state: ''
});
r.get('/redirect', (req, res) => {
res.redirect(authorizationUri);
});
// Callback service parsing the authorization token and asking for the access token
r.get('/callback', async (req, res) => {
const code = req.query.code as string;
const options = {
code,
redirect_uri: conf.redirect_uri
};
try {
const accessToken = await client.getToken(options);
return res.status(200).json(accessToken.token);
} catch (error) {
console.error('Access Token Error', error.message);
return res.status(500).redirect(`/error?message=${encodeURIComponent('Autenticazione fallita')}`);
}
});
}

@ -38,6 +38,7 @@ import {
import { initialDatabaseValue } from './db/example-data'
import { validateObjectKeys } from '../shared/utils'
import { setupOauth } from './auth'
export async function createApiRouter() {
type SessionId = Opaque<string, string, 'session'>
@ -70,6 +71,11 @@ export async function createApiRouter() {
r.use(bodyParser.json())
r.use(cookieParser())
const authRouter: Router = express.Router()
setupOauth(authRouter)
r.use('/auth', authRouter)
r.get('/api/status', (req, res) => {
res.json({ url: req.originalUrl, status: 'ok' })
})
@ -243,7 +249,7 @@ export async function createApiRouter() {
let queryUser = (req.query.user ?? null) as UserId | null
let queryProblem = (req.query.problem ?? null) as ProblemId | null
let isPublic = (req.query.public === '')
const requestUser = await getRequestUser(req)
let solutions = await getSolutions(db)
@ -256,10 +262,10 @@ export async function createApiRouter() {
solutions = solutions.filter(s => s.sentBy === queryUser)
}
if(isPublic) {
if (isPublic) {
solutions = solutions.filter(s => s.visible)
}
// filtra rispetto ai problemi
if (queryProblem !== null) {
solutions = solutions.filter(s => s.forProblem === queryProblem)

Loading…
Cancel
Save