gancio-upstream/server/api/controller/oauth.js

164 lines
4.5 KiB
JavaScript
Raw Normal View History

const crypto = require('crypto')
const { promisify } = require('util')
const randomBytes = promisify(crypto.randomBytes)
2020-06-27 02:10:10 +02:00
const OAuthClient = require('../models/oauth_client')
const OAuthToken = require('../models/oauth_token')
const OAuthCode = require('../models/oauth_code')
const User = require('../models/user')
2021-03-05 14:17:10 +01:00
const log = require('../../log')
const dayjs = require('dayjs')
2020-01-21 01:24:10 +01:00
async function randomString (len = 16) {
const bytes = await randomBytes(len * 8)
return crypto
.createHash('sha1')
.update(bytes)
.digest('hex')
}
const oauthController = {
2020-01-21 01:24:10 +01:00
// create client => http:///gancio.org/oauth#create-client
async createClient (req, res) {
2020-01-21 01:24:10 +01:00
// only write scope is supported
2020-01-21 17:33:33 +01:00
if (req.body.scopes && req.body.scopes !== 'event:write') {
2020-01-21 01:24:10 +01:00
return res.status(422).json({ error: 'Invalid scopes' })
}
const client = {
2020-01-21 01:24:10 +01:00
id: await randomString(256),
name: req.body.client_name,
2020-01-21 01:24:10 +01:00
redirectUris: req.body.redirect_uris,
2020-01-21 17:33:33 +01:00
scopes: req.body.scopes || 'event:write',
2020-01-21 01:24:10 +01:00
website: req.body.website,
client_secret: await randomString(256)
}
2020-01-21 01:24:10 +01:00
try {
await OAuthClient.create(client)
client.client_id = client.id
delete client.id
res.json(client)
} catch (e) {
2021-03-05 14:17:10 +01:00
log.error(e)
2020-01-21 01:24:10 +01:00
res.status(400).json(e)
}
},
2020-01-21 17:33:33 +01:00
async getClient (req, res) {
const client = await OAuthClient.findByPk(req.params.client_id, { raw: true })
if (!client) {
return res.status(404).send('Not found!')
}
res.json({
client_id: client.id,
redirect_uris: client.redirectUris,
name: client.name,
website: client.website,
scopes: client.scopes
})
},
2020-01-21 01:24:10 +01:00
async getClients (req, res) {
const tokens = await OAuthToken.findAll({
include: [{ model: User, where: { id: req.user.id } }, { model: OAuthClient, as: 'client' }],
raw: true,
nest: true
})
res.json(tokens)
},
model: {
2020-01-21 01:24:10 +01:00
/**
* Invoked to retrieve an existing access token previously saved through #saveToken().
* https://oauth2-server.readthedocs.io/en/latest/model/spec.html#getaccesstoken-accesstoken-callback
* */
async getAccessToken (accessToken) {
const oauth_token = await OAuthToken.findByPk(accessToken,
{ include: [{ model: User, attributes: { exclude: ['password'] } }, { model: OAuthClient, as: 'client' }] })
2020-01-21 01:24:10 +01:00
return oauth_token
},
/**
2020-01-27 00:47:03 +01:00
* Invoked to retrieve a client using a client id or a client id/client secret combination, depend on the grant type.
2020-01-21 01:24:10 +01:00
*/
async getClient (client_id, client_secret) {
const client = await OAuthClient.findByPk(client_id, { raw: true })
if (client_secret && client_secret !== client.client_secret) {
return false
}
2020-01-27 00:47:03 +01:00
if (client) { client.grants = ['authorization_code', 'password'] }
2020-01-21 01:24:10 +01:00
return client
},
async getRefreshToken (refresh_token) {
const oauth_token = await OAuthToken.findOne({ where: { refresh_token }, raw: true })
return oauth_token
},
async getAuthorizationCode (code) {
const oauth_code = await OAuthCode.findByPk(code,
2020-01-30 23:43:58 +01:00
{ include: [User, { model: OAuthClient, as: 'client' }] })
2020-01-21 01:24:10 +01:00
return oauth_code
},
2020-01-21 01:24:10 +01:00
async saveToken (token, client, user) {
token.userId = user.id
2020-01-30 23:43:58 +01:00
token.clientId = client.id
2020-01-21 01:24:10 +01:00
const oauth_token = await OAuthToken.create(token)
oauth_token.client = client
oauth_token.user = user
return oauth_token
},
async revokeAuthorizationCode (code) {
2020-01-30 23:43:58 +01:00
const oauth_code = await OAuthCode.findByPk(code.authorizationCode)
2020-01-21 01:24:10 +01:00
return oauth_code.destroy()
},
2020-01-27 00:47:03 +01:00
async getUser (username, password) {
const user = await User.findOne({ where: { email: username } })
if (!user || !user.is_active) {
return false
}
// check if password matches
if (await user.comparePassword(password)) {
return user
}
return false
},
2020-01-21 01:24:10 +01:00
async saveAuthorizationCode (code, client, user) {
code.userId = user.id
2020-01-30 23:43:58 +01:00
code.clientId = client.id
2021-03-05 14:17:10 +01:00
code.expiresAt = dayjs(code.expiresAt).toDate()
const ret = await OAuthCode.create(code)
2020-01-21 01:24:10 +01:00
return ret
2020-01-27 00:47:03 +01:00
},
2020-01-30 23:43:58 +01:00
// TODO
2020-01-27 00:47:03 +01:00
verifyScope (token, scope) {
2021-05-19 16:38:22 +02:00
// const userScope = [
// 'user:remove',
// 'user:update',
// 'event:write',
// 'event:remove'
// ]
log.debug(`VERIFY SCOPE ${scope} ${token.user.email}`)
if (token.user.is_admin && token.user.is_active) {
2020-01-27 00:47:03 +01:00
return true
} else {
2021-05-19 16:38:22 +02:00
return false
2020-01-27 00:47:03 +01:00
}
}
2020-01-21 01:24:10 +01:00
}
}
module.exports = oauthController