mirror of
https://github.com/verdaccio/verdaccio.git
synced 2025-04-01 02:42:23 -05:00
encrypt user+pass instead of tokens for now
This commit is contained in:
parent
691bdb3a92
commit
cf71b9dc9e
6 changed files with 113 additions and 54 deletions
58
lib/auth.js
58
lib/auth.js
|
@ -11,7 +11,7 @@ function Auth(config) {
|
|||
var self = Object.create(Auth.prototype)
|
||||
self.config = config
|
||||
self.logger = Logger.logger.child({ sub: 'auth' })
|
||||
self.secret = config.secret || Crypto.pseudoRandomBytes(32)
|
||||
self.secret = config.secret
|
||||
|
||||
var stuff = {
|
||||
config: config,
|
||||
|
@ -152,11 +152,17 @@ Auth.prototype.basic_middleware = function() {
|
|||
return next( Error[400]('bad authorization header') )
|
||||
|
||||
var scheme = parts[0]
|
||||
var credentials = Buffer(parts[1], 'base64').toString()
|
||||
var index = credentials.indexOf(':')
|
||||
|
||||
if (scheme !== 'Basic' || index < 0)
|
||||
if (scheme === 'Basic') {
|
||||
var credentials = Buffer(parts[1], 'base64').toString()
|
||||
} else if (scheme === 'Bearer') {
|
||||
var credentials = self.aes_decrypt(Buffer(parts[1], 'base64')).toString('utf8')
|
||||
if (!credentials) return next()
|
||||
} else {
|
||||
return next()
|
||||
}
|
||||
|
||||
var index = credentials.indexOf(':')
|
||||
if (index < 0) return next()
|
||||
|
||||
var user = credentials.slice(0, index)
|
||||
var pass = credentials.slice(index + 1)
|
||||
|
@ -229,15 +235,33 @@ Auth.prototype.cookie_middleware = function() {
|
|||
var token = req.cookies.get('token')
|
||||
if (token == null) return next()
|
||||
|
||||
try {
|
||||
var user = self.decode_token(token, 60*60 /* 1 hour */)
|
||||
/*try {
|
||||
var user = self.decode_token(token, 60*60)
|
||||
} catch(err) {
|
||||
return next()
|
||||
}
|
||||
|
||||
req.remote_user = AuthenticatedUser(user.u, user.g)
|
||||
req.remote_user.token = token
|
||||
next()
|
||||
next()*/
|
||||
var credentials = self.aes_decrypt(Buffer(token, 'base64')).toString('utf8')
|
||||
if (!credentials) return next()
|
||||
|
||||
var index = credentials.indexOf(':')
|
||||
if (index < 0) return next()
|
||||
|
||||
var user = credentials.slice(0, index)
|
||||
var pass = credentials.slice(index + 1)
|
||||
|
||||
self.authenticate(user, pass, function(err, user) {
|
||||
if (!err) {
|
||||
req.remote_user = user
|
||||
next()
|
||||
} else {
|
||||
req.remote_user = AnonymousUser()
|
||||
next(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,6 +300,24 @@ Auth.prototype.decode_token = function(str, expire_time) {
|
|||
return data
|
||||
}
|
||||
|
||||
Auth.prototype.aes_encrypt = function(buf) {
|
||||
var c = Crypto.createCipher('aes192', this.secret)
|
||||
var b1 = c.update(buf)
|
||||
var b2 = c.final()
|
||||
return Buffer.concat([ b1, b2 ])
|
||||
}
|
||||
|
||||
Auth.prototype.aes_decrypt = function(buf) {
|
||||
try {
|
||||
var c = Crypto.createDecipher('aes192', this.secret)
|
||||
var b1 = c.update(buf)
|
||||
var b2 = c.final()
|
||||
} catch(_) {
|
||||
return Buffer(0)
|
||||
}
|
||||
return Buffer.concat([ b1, b2 ])
|
||||
}
|
||||
|
||||
function AnonymousUser() {
|
||||
return {
|
||||
name: undefined,
|
||||
|
|
|
@ -3,7 +3,7 @@ var Crypto = require('crypto')
|
|||
var Error = require('http-errors')
|
||||
var minimatch = require('minimatch')
|
||||
var Path = require('path')
|
||||
var LocalList = require('./local-list')
|
||||
var LocalData = require('./local-data')
|
||||
var Utils = require('./utils')
|
||||
|
||||
// [[a, [b, c]], d] -> [a, b, c, d]
|
||||
|
@ -29,12 +29,21 @@ function Config(config) {
|
|||
assert.equal(typeof(config), 'object', 'CONFIG: it doesn\'t look like a valid config file')
|
||||
|
||||
assert(self.storage, 'CONFIG: storage path not defined')
|
||||
self.localList = LocalList(
|
||||
self.localList = LocalData(
|
||||
Path.join(
|
||||
Path.resolve(Path.dirname(self.self_path), self.storage),
|
||||
'.sinopia-db.json'
|
||||
)
|
||||
)
|
||||
if (!self.secret) {
|
||||
self.secret = self.localList.data.secret
|
||||
|
||||
if (!self.secret) {
|
||||
self.secret = Crypto.pseudoRandomBytes(32).toString('hex')
|
||||
self.localList.data.secret = self.secret
|
||||
self.localList.sync()
|
||||
}
|
||||
}
|
||||
|
||||
var users = {all:true, anonymous:true, 'undefined':true, owner:true, none:true}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ module.exports = function(config, auth, storage) {
|
|||
app.param('anything', match(/.*/))
|
||||
|
||||
app.use(auth.basic_middleware())
|
||||
app.use(auth.bearer_middleware())
|
||||
//app.use(auth.bearer_middleware())
|
||||
app.use(expressJson5({ strict: false, limit: config.max_body_size || '10mb' }))
|
||||
app.use(Middleware.anti_loop(config))
|
||||
|
||||
|
@ -113,11 +113,15 @@ module.exports = function(config, auth, storage) {
|
|||
})
|
||||
|
||||
app.put('/-/user/:org_couchdb_user/:_rev?/:revision?', function(req, res, next) {
|
||||
var token = (req.body.name && req.body.password)
|
||||
? auth.aes_encrypt(req.body.name + ':' + req.body.password).toString('base64')
|
||||
: undefined
|
||||
if (req.remote_user.name != null) {
|
||||
res.status(201)
|
||||
return next({
|
||||
ok: "you are authenticated as '" + req.remote_user.name + "'",
|
||||
token: auth.issue_token(req.remote_user),
|
||||
//token: auth.issue_token(req.remote_user),
|
||||
token: token,
|
||||
})
|
||||
} else {
|
||||
if (typeof(req.body.name) !== 'string' || typeof(req.body.password) !== 'string') {
|
||||
|
@ -141,7 +145,8 @@ module.exports = function(config, auth, storage) {
|
|||
res.status(201)
|
||||
return next({
|
||||
ok: "user '" + req.body.name + "' created",
|
||||
token: auth.issue_token(req.remote_user),
|
||||
//token: auth.issue_token(req.remote_user),
|
||||
token: token,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -80,7 +80,10 @@ module.exports = function(config, auth, storage) {
|
|||
auth.authenticate(req.body.user, req.body.pass, function(err, user) {
|
||||
if (!err) {
|
||||
req.remote_user = user
|
||||
res.cookies.set('token', auth.issue_token(req.remote_user))
|
||||
//res.cookies.set('token', auth.issue_token(req.remote_user))
|
||||
|
||||
var str = req.body.user + ':' + req.body.pass
|
||||
res.cookies.set('token', auth.aes_encrypt(str).toString('base64'))
|
||||
}
|
||||
|
||||
var base = config.url_prefix || req.protocol + '://' + req.get('host')
|
||||
|
|
40
lib/local-data.js
Normal file
40
lib/local-data.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
var fs = require('fs')
|
||||
|
||||
module.exports = LocalData
|
||||
|
||||
function LocalData(path) {
|
||||
var self = Object.create(LocalData.prototype)
|
||||
self.path = path
|
||||
try {
|
||||
self.data = JSON.parse(fs.readFileSync(self.path, 'utf8'))
|
||||
} catch(_) {
|
||||
self.data = { list: [] }
|
||||
}
|
||||
return self
|
||||
}
|
||||
|
||||
LocalData.prototype.add = function(name) {
|
||||
if (this.data.list.indexOf(name) === -1) {
|
||||
this.data.list.push(name)
|
||||
this.sync()
|
||||
}
|
||||
}
|
||||
|
||||
LocalData.prototype.remove = function(name) {
|
||||
var i = this.data.list.indexOf(name)
|
||||
if (i !== -1) {
|
||||
this.data.list.splice(i, 1)
|
||||
}
|
||||
|
||||
this.sync()
|
||||
}
|
||||
|
||||
LocalData.prototype.get = function() {
|
||||
return this.data.list
|
||||
}
|
||||
|
||||
LocalData.prototype.sync = function() {
|
||||
// Uses sync to prevent ugly race condition
|
||||
fs.writeFileSync(this.path, JSON.stringify(this.data))
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
var fs = require('fs')
|
||||
|
||||
module.exports = LocalList
|
||||
|
||||
function LocalList(path) {
|
||||
var self = Object.create(LocalList.prototype)
|
||||
self.path = path
|
||||
try {
|
||||
self.list = JSON.parse(fs.readFileSync(self.path, 'utf8')).list
|
||||
} catch(_) {
|
||||
self.list = []
|
||||
}
|
||||
return self
|
||||
}
|
||||
|
||||
LocalList.prototype.add = function(name) {
|
||||
if (this.list.indexOf(name) === -1) {
|
||||
this.list.push(name)
|
||||
this.sync()
|
||||
}
|
||||
}
|
||||
|
||||
LocalList.prototype.remove = function(name) {
|
||||
var i = this.list.indexOf(name)
|
||||
if (i !== -1) {
|
||||
this.list.splice(i, 1)
|
||||
}
|
||||
|
||||
this.sync()
|
||||
}
|
||||
|
||||
LocalList.prototype.get = function() {
|
||||
return this.list
|
||||
}
|
||||
|
||||
LocalList.prototype.sync = function() {
|
||||
// Uses sync to prevent ugly race condition
|
||||
fs.writeFileSync(this.path, JSON.stringify({ list: this.list }))
|
||||
}
|
||||
|
Loading…
Add table
Reference in a new issue