You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

91 lines
3.0 KiB
TypeScript

import { Router } from 'express'
import { AuthorizationCode } from 'simple-oauth2'
import fetch from 'node-fetch'
import { DatabaseConnection, getUser, createUser } from './db/database'
import { UserId } from '../shared/model'
import { SessionService } from './routes'
import { prependBaseUrl } from '../shared/utils'
export function setupOAuth(r: Router, db: DatabaseConnection, sessions: SessionService) {
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)
console.log(accessToken.token.access_token)
const userInfo = await (
await fetch(process.env.OAUTH_USER_INFO_URL ?? '', {
method: 'GET',
headers: {
Authorization: 'Bearer ' + accessToken.token.access_token,
},
})
).json()
type UserInfo = { name: string; email: string }
// Parse user info into a sensible struct
const authUser = {
id: (userInfo as UserInfo).email.split('@')[0] as UserId,
fullName: (userInfo as UserInfo).name
.split(' ')
.map(s => s.substring(0, 1) + s.substring(1).toLowerCase())
.join(' '),
}
const user = await getUser(db, authUser.id)
if (!user) {
await createUser(db, {
id: authUser.id,
fullName: authUser.fullName,
role: 'student',
})
}
res.cookie('sid', sessions.createSession(authUser.id), { maxAge: 1000 * 60 * 60 * 24 * 7 })
return res.status(200).redirect(prependBaseUrl('/'))
} catch (error) {
console.error('Access Token Error', error.message)
return res.status(500).redirect(prependBaseUrl(`/error?message=${encodeURIComponent('Autenticazione fallita')}`))
}
})
}