big oauth improvements
This commit is contained in:
@@ -1,57 +1,117 @@
|
||||
const crypto = require('crypto')
|
||||
const { promisify } = require('util')
|
||||
const randomBytes = promisify(crypto.randomBytes)
|
||||
const { oauth_client: OAuthClient, oauth_token: OAuthToken,
|
||||
oauth_code: OAuthCode } = require('../models')
|
||||
const {
|
||||
oauth_client: OAuthClient, oauth_token: OAuthToken,
|
||||
oauth_code: OAuthCode, user: User
|
||||
} = require('../models')
|
||||
const debug = require('debug')('oauth')
|
||||
|
||||
async function randomString(len = 16) {
|
||||
const bytes = await randomBytes(len*8)
|
||||
async function randomString (len = 16) {
|
||||
const bytes = await randomBytes(len * 8)
|
||||
return crypto
|
||||
.createHash('sha1')
|
||||
.update(bytes)
|
||||
.digest('hex')
|
||||
}
|
||||
|
||||
|
||||
const oauthController = {
|
||||
|
||||
async getClient (req, res) {
|
||||
const client_id = req.params.client_id
|
||||
const client = await OAuthClient.findOne({ where: { client_id }})
|
||||
console.error('ma non ho trovato il client ', client_id, client )
|
||||
res.json(client)
|
||||
},
|
||||
|
||||
// create client => http:///gancio.org/oauth#create-client
|
||||
async createClient (req, res) {
|
||||
debug('Create client ', req.body.client_name)
|
||||
// only write scope is supported
|
||||
if (req.body.scopes && req.body.scopes !== 'write') {
|
||||
return res.status(422).json({ error: 'Invalid scopes' })
|
||||
}
|
||||
|
||||
const client = {
|
||||
id: await randomString(256),
|
||||
name: req.body.client_name,
|
||||
redirectUris: req.body.redirect_uris || 'urn:ietf:wg:oauth:2.0:oob',
|
||||
redirectUris: req.body.redirect_uris,
|
||||
scopes: req.body.scopes || 'write',
|
||||
client_id: await randomString(256),
|
||||
website: req.body.website,
|
||||
client_secret: await randomString(256)
|
||||
}
|
||||
res.json(await OAuthClient.create(client))
|
||||
|
||||
try {
|
||||
await OAuthClient.create(client)
|
||||
client.client_id = client.id
|
||||
delete client.id
|
||||
res.json(client)
|
||||
} catch (e) {
|
||||
debug(e)
|
||||
res.status(400).json(e)
|
||||
}
|
||||
},
|
||||
|
||||
async associate (req, res) {
|
||||
const { client_id, redirect_uri, response_type } = req.query
|
||||
console.error('dentro associate ', client_id, redirect_uri, response_type )
|
||||
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: {
|
||||
async getClient (clientId, clientSecret) {
|
||||
console.error(`model getClient ${clientId} / ${clientSecret}`)
|
||||
const client = await OAuthClient.findByPk(clientId)
|
||||
client.grants = ['authorization_code']
|
||||
return client || false
|
||||
|
||||
/**
|
||||
* 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: [User, { model: OAuthClient, as: 'client' }], nest: true, raw: true })
|
||||
return oauth_token
|
||||
},
|
||||
|
||||
async saveAuthorizationCode(code, client, user) {
|
||||
console.error('dentro save auth code ', client, user, code)
|
||||
/**
|
||||
* Invoked to retrieve a client using a client id or a client id/client secret combination, depending on the grant type.
|
||||
*/
|
||||
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
|
||||
}
|
||||
|
||||
if (client) { client.grants = ['authorization_code'] }
|
||||
|
||||
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,
|
||||
{ include: [User, { type: OAuthClient, as: 'client' }], nest: true, raw: true })
|
||||
return oauth_code
|
||||
},
|
||||
|
||||
async saveToken (token, client, user) {
|
||||
token.userId = user.id
|
||||
token.oauthClientId = client.id
|
||||
const oauth_token = await OAuthToken.create(token)
|
||||
oauth_token.client = client
|
||||
oauth_token.user = user
|
||||
return oauth_token
|
||||
},
|
||||
|
||||
async revokeAuthorizationCode (code) {
|
||||
const oauth_code = await OAuthCode.findByPk(code)
|
||||
return oauth_code.destroy()
|
||||
},
|
||||
|
||||
async saveAuthorizationCode (code, client, user) {
|
||||
code.userId = user.id
|
||||
code.oauthClientId = client.id
|
||||
const ret = await OAuthCode.create(code)
|
||||
return ret
|
||||
return ret
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ const instanceController = require('./controller/instance')
|
||||
const apUserController = require('./controller/ap_user')
|
||||
const resourceController = require('./controller/resource')
|
||||
const oauthController = require('./controller/oauth')
|
||||
const oauth = require('./oauth')
|
||||
|
||||
const storage = require('./storage')
|
||||
const upload = multer({ storage })
|
||||
@@ -82,7 +83,7 @@ api.get('/event/:event_id.:format?', cors, eventController.get)
|
||||
api.get('/export/:type', cors, exportController.export)
|
||||
|
||||
// get events in this range
|
||||
api.get('/event/:month/:year', cors, eventController.getAll)
|
||||
// api.get('/event/:month/:year', cors, eventController.getAll)
|
||||
api.get('/event', cors, eventController.select)
|
||||
|
||||
api.get('/instances', isAdmin, instanceController.getAll)
|
||||
@@ -93,9 +94,12 @@ api.put('/resources/:resource_id', isAdmin, resourceController.hide)
|
||||
api.delete('/resources/:resource_id', isAdmin, resourceController.remove)
|
||||
api.get('/resources', isAdmin, resourceController.getAll)
|
||||
|
||||
api.get('/client/:client_id', isAuth, oauthController.getClient)
|
||||
api.get('/clients', isAuth, oauthController.getClients)
|
||||
api.post('/client', oauthController.createClient)
|
||||
|
||||
// api.get('/verify', oauth.oauthServer.authenticate(), (req, res) => {
|
||||
// })
|
||||
|
||||
// Handle 404
|
||||
api.use((req, res) => {
|
||||
debug('404 Page not found: %s', req.path)
|
||||
@@ -104,7 +108,7 @@ api.use((req, res) => {
|
||||
|
||||
// Handle 500
|
||||
api.use((error, req, res, next) => {
|
||||
debug(error)
|
||||
debug(error.toString())
|
||||
res.status(500).send('500: Internal Server Error')
|
||||
})
|
||||
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
|
||||
module.exports = (sequelize, DataTypes) => {
|
||||
const OAuthClient = sequelize.define('oauth_client', {
|
||||
client_id: {
|
||||
id: {
|
||||
type: DataTypes.STRING,
|
||||
primaryKey: true
|
||||
primaryKey: true,
|
||||
allowNull: false
|
||||
},
|
||||
name: DataTypes.STRING,
|
||||
scopes: DataTypes.STRING,
|
||||
client_secret: DataTypes.STRING,
|
||||
redirectUris: DataTypes.STRING
|
||||
scopes: DataTypes.STRING,
|
||||
redirectUris: DataTypes.STRING,
|
||||
website: DataTypes.STRING
|
||||
}, {})
|
||||
|
||||
OAuthClient.associate = function (models) {
|
||||
OAuthClient.belongsTo(models.user)
|
||||
}
|
||||
|
||||
return OAuthClient
|
||||
}
|
||||
|
||||
@@ -5,13 +5,14 @@ module.exports = (sequelize, DataTypes) => {
|
||||
type: DataTypes.STRING,
|
||||
primaryKey: true
|
||||
},
|
||||
expiresAt: DataTypes.DATE,
|
||||
scope: DataTypes.STRING,
|
||||
redirect_uri: DataTypes.STRING
|
||||
}, {})
|
||||
|
||||
OAuthCode.associate = function (models) {
|
||||
OAuthCode.belongsTo(models.user)
|
||||
OAuthCode.belongsTo(models.oauth_client)
|
||||
OAuthCode.belongsTo(models.oauth_client, { as: 'client' })
|
||||
}
|
||||
|
||||
return OAuthCode
|
||||
|
||||
@@ -1,14 +1,30 @@
|
||||
|
||||
module.exports = (sequelize, DataTypes) => {
|
||||
const OAuthToken = sequelize.define('oauth_token', {
|
||||
access_token: DataTypes.STRING,
|
||||
refresh_token: DataTypes.STRING,
|
||||
scope: DataTypes.STRING,
|
||||
accessToken: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
primaryKey: true
|
||||
},
|
||||
accessTokenExpiresAt: {
|
||||
type: DataTypes.DATE,
|
||||
get () {
|
||||
return new Date(this.getDataValue('accesTokenExpiresAt'))
|
||||
}
|
||||
},
|
||||
refreshToken: DataTypes.STRING,
|
||||
refreshTokenExpiresAt: {
|
||||
type: DataTypes.DATE,
|
||||
get () {
|
||||
return new Date(this.getDataValue('accesTokenExpiresAt'))
|
||||
}
|
||||
},
|
||||
scope: DataTypes.STRING
|
||||
}, {})
|
||||
|
||||
OAuthToken.associate = function (models) {
|
||||
OAuthToken.belongsTo(models.user)
|
||||
OAuthToken.belongsTo(models.oauth_client)
|
||||
OAuthToken.belongsTo(models.oauth_client, { as: 'client' })
|
||||
}
|
||||
|
||||
return OAuthToken
|
||||
|
||||
@@ -2,41 +2,36 @@ const express = require('express')
|
||||
const OAuthServer = require('express-oauth-server')
|
||||
const oauth = express.Router()
|
||||
const oauthController = require('./controller/oauth')
|
||||
const debug = require('debug')('oauth')
|
||||
|
||||
const oauthServer = new OAuthServer({
|
||||
model: oauthController.model,
|
||||
allowEmptyState: true,
|
||||
useErrorHandler: true,
|
||||
continueMiddleware: false,
|
||||
debug: true,
|
||||
authenticateHandler: { handle(req) { return req.user } }
|
||||
authenticateHandler: {
|
||||
handle (req) {
|
||||
if (!req.user) {
|
||||
throw new Error('Not authenticated!')
|
||||
}
|
||||
return req.user
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
oauth.oauth = oauthServer
|
||||
oauth.use(express.urlencoded({ extended: false }))
|
||||
oauth.oauthServer = oauthServer
|
||||
oauth.use(express.json())
|
||||
oauth.use(express.urlencoded({ extended: false }))
|
||||
|
||||
// post token
|
||||
oauth.post('/token', oauthServer.token())
|
||||
|
||||
oauth.get('/authorize', async (req, res, next) => {
|
||||
if (!req.user) {
|
||||
return res.redirect(`/login?redirect=${req.path}&client_id=${req.query.client_id}&redirect_uri=${req.query.redirect_uri}`)
|
||||
}
|
||||
|
||||
return oauthServer.authorize()
|
||||
})
|
||||
|
||||
oauth.post('/authorize', (req, res, next) => {
|
||||
if (!req.user) {
|
||||
return res.redirect(`/login?redirect=${req.path}&client_id=${req.query.client_id}&redirect_uri=${req.query.redirect_uri}`)
|
||||
}
|
||||
|
||||
return oauthServer.authorize()
|
||||
})
|
||||
oauth.get('/authorize', oauthServer.authorize())
|
||||
|
||||
oauth.use((err, req, res, next) => {
|
||||
res.status(500).json(err)
|
||||
const error_msg = err.toString()
|
||||
debug(err)
|
||||
res.status(500).send(error_msg)
|
||||
})
|
||||
|
||||
// oauth.post('/login', )
|
||||
|
||||
module.exports = oauth
|
||||
module.exports = oauth
|
||||
|
||||
Reference in New Issue
Block a user