Browse Source

Initial Commit

Adam Shumann 3 years ago
commit
57d53491eb
9 changed files with 212 additions and 0 deletions
  1. 1
    0
      .gitignore
  2. 21
    0
      LICENSE
  3. 18
    0
      README.md
  4. 4
    0
      index.js
  5. 47
    0
      lib/auth.js
  6. 71
    0
      lib/backend.js
  7. 19
    0
      lib/engine.js
  8. 8
    0
      lib/index.js
  9. 23
    0
      package.json

+ 1
- 0
.gitignore View File

@@ -0,0 +1 @@
1
+node_modules

+ 21
- 0
LICENSE View File

@@ -0,0 +1,21 @@
1
+MIT License
2
+
3
+Copyright (c) Adam Shumann 2016
4
+
5
+Permission is hereby granted, free of charge, to any person obtaining a copy
6
+of this software and associated documentation files (the "Software"), to deal
7
+in the Software without restriction, including without limitation the rights
8
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+copies of the Software, and to permit persons to whom the Software is
10
+furnished to do so, subject to the following conditions:
11
+
12
+The above copyright notice and this permission notice shall be included in all
13
+copies or substantial portions of the Software.
14
+
15
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+SOFTWARE.

+ 18
- 0
README.md View File

@@ -0,0 +1,18 @@
1
+# screepsmod-auth
2
+
3
+## This adds the client to the backend as /client
4
+
5
+# Installation 
6
+
7
+## The NPM way
8
+1. Make sure you have [ModLoader](https://github.com/ScreepsMods/screepsmod-modloader) installed
9
+2. `npm install screepsmod-auth` in your mods folder.
10
+3. Thats it!
11
+
12
+# Usage
13
+1. Open the steam screeps client
14
+2. In console, run `setPassword('YourDesiredPassword')`
15
+3. Now you should be able to login via API or a web client via [ScreepsMod-Client](https://github.com/ScreepsMods/screepsmod-client)
16
+
17
+# Notes:
18
+This is NOT compatible with screepsmod-apitoken, having both installed may result in issues.

+ 4
- 0
index.js View File

@@ -0,0 +1,4 @@
1
+module.exports = function(config){
2
+  if(config.backend || config.engine)
3
+    require('./lib')(config)
4
+}

+ 47
- 0
lib/auth.js View File

@@ -0,0 +1,47 @@
1
+const crypto = require('crypto')
2
+
3
+class Auth{
4
+  constructor(opts){
5
+    this.opts = opts = opts || {};
6
+    opts.saltlen = opts.saltlen || 32;
7
+    opts.iterations = opts.iterations || 25000;
8
+    opts.keylen = opts.keylen || 512;
9
+    opts.encoding = opts.encoding || 'hex';
10
+    opts.digestAlgorithm = opts.digestAlgorithm || 'sha256'; // To get a list of supported hashes use crypto.getHashes()
11
+    opts.passwordValidator = opts.passwordValidator || function(password, cb) { cb(null); };
12
+  }
13
+  
14
+  encrypt_password(password){
15
+    return new Promise((resolve,reject)=>{
16
+      crypto.randomBytes(this.opts.saltlen,(err,buf)=>{
17
+        if(err) return reject(err)
18
+        let salt = buf.toString(this.opts.encoding)
19
+        this.pbkdf2(password,salt,(err,rawhash)=>{
20
+          if(err) return reject(err)
21
+          let hash = new Buffer(rawhash,'binary').toString(this.opts.encoding)
22
+          resolve({
23
+            pass: hash,
24
+            salt: salt
25
+          })
26
+        })
27
+      })
28
+    })
29
+  }
30
+
31
+  verify_password(salt,pass,proposed){
32
+    return new Promise((resolve,reject)=>{
33
+      this.pbkdf2(proposed,salt,(err,rawhash)=>{
34
+        if(err) return reject(err)
35
+        let hash = new Buffer(rawhash,'binary').toString(this.opts.encoding)
36
+        resolve(hash == pass)
37
+      })
38
+    })
39
+  }
40
+
41
+  pbkdf2(password,salt,callback){
42
+    crypto.pbkdf2(new Buffer(password), new Buffer(salt), this.opts.iterations, this.opts.keylen, this.opts.digestAlgorithm, callback);
43
+  }
44
+
45
+}
46
+module.exports = Auth
47
+

+ 71
- 0
lib/backend.js View File

@@ -0,0 +1,71 @@
1
+const path = require('path')
2
+const express = require('express')
3
+const bodyParser = require('body-parser')
4
+const passport = require('passport')
5
+const LocalStrategy = require('passport-local').Strategy
6
+const BasicStrategy = require('passport-http').BasicStrategy
7
+const basicAuth = require('basic-auth')
8
+const authlib = require(path.join(path.dirname(require.main.filename), '../lib/authlib'))
9
+
10
+let storage,auth;
11
+
12
+module.exports = function(config,authIns){
13
+  auth = authIns
14
+  storage = config.common.storage
15
+  config.auth.router = new express.Router()
16
+  let onExpressPreConfig = config.backend.onExpressPreConfig
17
+  config.backend.onExpressPreConfig = function(app){
18
+    app.use(config.auth.router)
19
+    return onExpressPreConfig(app)
20
+  }
21
+  setupRouter(config)
22
+}
23
+
24
+function setupRouter(config){
25
+  passport.use(new LocalStrategy({
26
+    usernameField: 'email',
27
+    session: false
28
+  },authUser))
29
+  passport.use(new BasicStrategy({
30
+    session: false
31
+  },authUser))
32
+  passport.serializeUser((u,d)=>d(null,u))
33
+  passport.deserializeUser((u,d)=>d(null,u))
34
+  let router = config.auth.router
35
+  router.use(passport.initialize())
36
+  router.post('/api/auth/signin',bodyParse,passport.authenticate(['local','basic']),(req,res)=>{
37
+    if(!req.user) return res.status(401).end('Unauthorized')
38
+    authlib.genToken(req.user._id)
39
+      .then(token => {
40
+        res.json({ ok: 1, token})
41
+      })
42
+      .catch(err=>res.status(500).end(err.stack || err.message))
43
+  })
44
+  router.use('/api/user/code',(req,res,next)=>{
45
+    if(req.method != 'POST') return next()
46
+    passport.authenticate('basic')(req,res,()=>{
47
+      if(!req.user) return next()
48
+      authlib.genToken(req.user._id)
49
+        .then(token => {
50
+          req.headers['x-token'] = token
51
+          req.headers['x-username'] = token
52
+          next()
53
+        }) 
54
+    })
55
+  })
56
+}
57
+
58
+function bodyParse(req,res,next){
59
+  bodyParser.json()(req,res,next)
60
+}
61
+
62
+function authUser(username,password,done){
63
+  storage.db.users.findOne({ $or:[{username: username},{email:username}] })
64
+  .then(user=>{
65
+    if(!user) return done(null, false)
66
+    return auth.verify_password(user.salt,user.password,password)
67
+      .then(valid=>valid?user:false)
68
+  })
69
+  .then(user=>done(null,user))
70
+  .catch(done)
71
+}

+ 19
- 0
lib/engine.js View File

@@ -0,0 +1,19 @@
1
+const Auth = require('./auth')
2
+
3
+module.exports = function engine(config,auth){
4
+  let storage = config.common.storage
5
+  config.engine.onPlayerSandbox = function (sandbox) {
6
+    sandbox.setPassword = function(password) {
7
+      console.log(auth)
8
+      auth.encrypt_password(password)
9
+      .then((obj)=>{
10
+        return storage.db.users.update({ _id: sandbox.module.user },{ $set: {
11
+          password: obj.pass,
12
+          salt: obj.salt
13
+        }})
14
+      })
15
+      .then((res)=>sandbox.console.log('Password Set',res))
16
+      .catch(err=>sandbox.console.error(err))
17
+    }
18
+  }
19
+}

+ 8
- 0
lib/index.js View File

@@ -0,0 +1,8 @@
1
+const Auth = require('./auth')
2
+
3
+module.exports = function(config){
4
+  let auth = new Auth()
5
+  config.auth = {}
6
+  if(config.engine) require('./engine')(config,auth)
7
+  if(config.backend) require('./backend')(config,auth)
8
+}

+ 23
- 0
package.json View File

@@ -0,0 +1,23 @@
1
+{
2
+  "name": "screepsmod-auth",
3
+  "version": "1.0.0",
4
+  "description": "",
5
+  "main": "index.js",
6
+  "scripts": {
7
+    "test": "echo \"Error: no test specified\" && exit 1"
8
+  },
9
+  "keywords": [
10
+    "screeps",
11
+    "mod"
12
+  ],
13
+  "author": "Adam Shumann",
14
+  "license": "MIT",
15
+  "dependencies": {
16
+    "basic-auth": "^1.0.4",
17
+    "body-parser": "^1.15.2",
18
+    "express": "^4.14.0",
19
+    "passport": "^0.3.2",
20
+    "passport-http": "^0.3.0",
21
+    "passport-local": "^1.0.0"
22
+  }
23
+}