Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Auth plugin

  • Loading branch information...
commit 26307a62f023ebdd3fe60bfb6fb1c44c36bc9e8d 1 parent ba7d850
@qyi qyi authored
View
3  lib/rithis-stack/index.coffee
@@ -35,8 +35,9 @@ defaultStack = (directory, name, plugin) ->
stack.plugins.push plugins.assets
stack.plugins.push plugins.bower
- stack.plugins.push plugins.crud
stack.plugins.push plugins.mongoose
+ stack.plugins.push plugins.auth
+ stack.plugins.push plugins.crud
stack.plugins.push plugin
View
98 lib/rithis-stack/plugins/auth.coffee
@@ -0,0 +1,98 @@
+sechash = require 'sechash'
+url = require 'url'
+expires = require 'expires'
+json = require 'json-output'
+
+module.exports = (stack, callback) ->
+ options =
@vslinko Owner
vslinko added a note

распластать в переменные, ибо они не конфигурируются

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ expires: '1 week'
+ authRoute: '/auth-token'
+ authParam: 'authToken'
+ authTokenHash:
+ algorithm: 'sha256'
+ iterations: 50
+
+ generateSalt = ->
+ sechash.basicHash 'sha1',
+ String((Math.random() + 2) * Math.random())
@vslinko Owner
vslinko added a note

Зачем такая магия да еще используя модули, вроде есть хеширование в самой ноде

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+
+ hashPassword = (password, salt) ->
+ sechash.strongHashSync password,
+ algorithm: options.authTokenHash.algorithm
+ iterations: options.authTokenHash.iterations
+ salt: salt
@vslinko Owner
vslinko added a note

тоже магия :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+
+ options.authTokenHash.salt = generateSalt()
@vslinko Owner
vslinko added a note

тоже переменная

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+
+ UserSchema = new stack.mongoose.Schema
+ username: type: "string", required: true
+ password: type: "string", required: true
+ salt: type: "string", required: true
+ token: type: "string"
@vslinko Owner
vslinko added a note

токенов должно быть много, ибо разные сессии

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ tokenExpire: type: Date
+ metadata: type: stack.mongoose.Schema.Types.Mixed
+
+ UserSchema.pre 'validate', (next) ->
+ @salt = generateSalt() unless @salt
+ next()
+
+ UserSchema.pre 'save', (next) ->
+ @password = hashPassword @password, @salt
+ next()
+
+ User = stack.connection.model "users", UserSchema
+
+ # Authenticate
+ stack.app.use (req, res, next) ->
+ uri = url.parse(req.url).pathname
+ return next() unless options.authRoute == uri
+
+ unless req.method == 'POST'
+ message = '/auth-token only supports POST requests'
+ return res.json json.error message
+ , 405
@vslinko Owner
vslinko added a note

Почему не заменить эти 8 строк на app.post '/auth-token', (req, res) ->

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+
+ errorCallback = (err, status) ->
+ res.json json.error err, status or 405
+
+ User.findOne username: req.body.username, (err, user) ->
+ if err
+ return errorCallback err
+
+ unless user
+ return errorCallback 'User does not exists', 404
+
+ if hashPassword(req.body.password, user.salt) != user.password
+ return errorCallback 'Invalid password', 401
+
+ authToken = sechash.strongHashSync(
+ user.username + '+' + user.password + '+' + options.expires
+ )
+
+ user.token = authToken
+ user.tokenExpire = new Date expires.after options.expires
+ user.save ->
+ res.json authToken: authToken
+
+ # Populate user
+ stack.app.use (req, res, next) ->
+ if req.query[options.authParam]
@vslinko Owner
vslinko added a note

Думаю стоит брать только из хидера

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ authToken = req.query[options.authParam]
+ else if req.body[options.authParam]
+ authToken = req.body[options.authParam]
+ else if req.get 'Authorization'
+ authToken = req.get('Authorization').replace 'Token ', ''
+
+ unless authToken
+ return next()
+
+ User.findOne token: authToken, (err, user) ->
+ return next() if err or !user
+ return next() if expires.expired user.tokenExpire
+
+ req.user =
+ username = user.username
+
+ next()
+
+ callback()
View
1  lib/rithis-stack/plugins/index.coffee
@@ -1,4 +1,5 @@
module.exports.assets = require "./assets"
+module.exports.auth = require "./auth"
module.exports.bower = require "./bower"
module.exports.crud = require "./crud"
module.exports.files = require "./files"
View
5 package.json
@@ -23,6 +23,9 @@
"mongoose": "~3.4",
"stylus": "~0.32",
"bower": "~0.6",
- "nib": "~0.9"
+ "nib": "~0.9",
+ "sechash": "~0.2.1",
+ "expires": "0.0.0",
+ "json-output": "0.0.1"
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.