From 291eaf85a5bf658888374a68862f6e8b44fb869c Mon Sep 17 00:00:00 2001 From: spiduler Date: Wed, 2 Sep 2020 10:18:55 +0900 Subject: [PATCH] first commit --- .gitignore | 3 ++ README.md | Bin 0 -> 40 bytes app/services.js | 89 +++++++++++++++++++++++++++++++ index.js | 139 ++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 25 +++++++++ storage/db.json | 11 ++++ 6 files changed, 267 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 app/services.js create mode 100644 index.js create mode 100644 package.json create mode 100644 storage/db.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b8ffe08 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +package-lock.json + diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..64d1ab1ad66728e7674aef71a0b51f6d02468535 GIT binary patch literal 40 pcmezWPnki1A(J7Ap@2b`ArVM|=yV{fgdvro97tC(@G@{Q007BO2p|9e literal 0 HcmV?d00001 diff --git a/app/services.js b/app/services.js new file mode 100644 index 0000000..bcf9514 --- /dev/null +++ b/app/services.js @@ -0,0 +1,89 @@ +var uuid = require('node-uuid'), + authCodes = {}, + accessTokens = {}, + tokenHeartbeats = {}, + clients = { + 'F8Nbz9gGUvLgdn8T': { + id: '1', + secret: 'Fesmx7hHCCMx7Cby7FhV2fAtf2NYEFzP5fCKuwEEdpf8hpnsnnQn9qYhNHt6SsDD', + grantTypes: ['client_credentials'] + }, + 'dev52VrnSufxEyKT': { + id: '2', + secret: 'nK2jnqhdWnrmAFDw9zWVueAqUQvSxmAyjf2Sz7ZrmYVSH5GSxER4rPQCuBUewF', + grantTypes: ['client_credentials'] + } + }; + +const services = { + flushExpiredTokens: function (maxAge) { + let oldTokens = []; + let now = new Date().getTime(); + for (let token in accessTokens) { + if (tokenHeartbeats[token] && tokenHeartbeats[token] < now - 1000 * maxAge) { + oldTokens.push(token) + delete accessTokens[token] + } + } + console.log('Flush expired tokens execution completed.', oldTokens) + }, + getAccessTokens: function () { + return accessTokens; + }, + getClients: function () { + return clients; + }, + heartbeat: { + puls: function (token) { + tokenHeartbeats[token] = new Date().getTime(); + }, + signal: function (authHeader) { + if (authHeader) { + let token = authHeader.split(' ').pop() + if (accessTokens[token]) { + services.heartbeat.puls(token) + return tokenHeartbeats[token]; + } + } + return false; + } + }, + clientService: { + getById: function (id, callback) { + return callback(null, clients[id]); + }, + isValidRedirectUri: function (/*client, requestedUri*/) { + return true; + } + }, + tokenService: { + generateToken: function (callback) { + callback(null, uuid.v4()); + }, + generateAuthorizationCode: function (callback) { + callback(null, uuid.v4()); + } + }, + authorizationService: { + saveAuthorizationCode: function (codeData, callback) { + authCodes[codeData.code] = codeData; + return callback(null, authCodes[codeData.code]); + }, + saveAccessToken: function (tokenData, callback) { + accessTokens[tokenData.access_token] = tokenData; + return callback(null, accessTokens[tokenData.access_token]); + }, + getAuthorizationCode: function (code, callback) { + return callback(null, authCodes[code]); + }, + getAccessToken: function (token, callback) { + return callback(null, accessTokens[token]); + } + }, + membershipService: { + areUserCredentialsValid: function (userName, password, scope, callback) { + return callback(null, true); + } + } +} +module.exports = services \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..eb86afb --- /dev/null +++ b/index.js @@ -0,0 +1,139 @@ +var proxy = require('express-http-proxy'), + express = require('express'), + expressLogging = require('express-logging'), + logger = require('logops'), + port = 32100, hostname = '127.0.0.1', + supportedScopes = ['profile', 'status', 'avatar'], + expiresIn = 3600, + low = require('lowdb'), + FileSync = require('lowdb/adapters/FileSync'), + HttpStatus = require('http-status-codes'), + cron = require('node-cron'); + +const services = require('./app/services'); +const adapter = new FileSync(__dirname + '/storage/db.json') +const db = low(adapter) + +db.get('authCodes').value() + .forEach(codeData => { + codeData.expiresDate = function () { + var d = new Date(); + d.setDate(d.getDate() + 2); + return d; + }(); + services.authorizationService.saveAuthorizationCode(codeData, function (n, codeData) { + // console.log(codeData) + }) + }); + +var OAuthServer = require('simple-oauth-server'), + oauthServer = new OAuthServer( + services.clientService, + services.tokenService, + services.authorizationService, + services.membershipService, + expiresIn, + supportedScopes + ); + +function authorize(request, response) { + response.statusCode = 403; + response.json({ code: 501, message: 'Not Implemented' }); + return true; + oauthServer.authorizeRequest(request, 'accountid', function (error, authorizationResult) { + if (error) { + response.statusCode = 400; + return response.end(JSON.stringify(error)); + } + // var code = require('url').parse(authorizationResult.redirectUri, true).query.code; + // response.statusCode = 302; + // response.setHeader('Location', 'http://localhost:8080/oauth/token?client_id=1&grant_type=authorization_code&client_secret=kittens&code=' + code); + + response.end(JSON.stringify(authorizationResult)); + }); +} + +function grantToken(request, response) { + oauthServer.grantAccessToken(request, function (error, token) { + if (error) { + console.log(error) + response.statusCode = 400; + return response.json(error); + } + if (services.getClients()[request.query.client_id].id == 1) { + services.heartbeat.puls(token.access_token); + } + response.json(token); + }); +} + +function apiEndpoint(request, response) { + console.log(oauthServer.validateAccessToken(request, function (error, validationResult) { + if (error) { + response.statusCode = 401; + return response.json(error); + } + response.json(validationResult); + })); +} + +function heartbeat(request, response) { + let updated = services.heartbeat.signal(request.headers.authorization); + response.json({ code: updated ? 200 : 400, data: updated }); +} + +cron.schedule('0 * * * * *', () => { + services.flushExpiredTokens(300); +}); + + +const app = express() +app.use(expressLogging(logger)); +const proxyFilter = function (req, res) { + return req.hostname == hostname ? true : new Promise(function (resolve) { + resolve(function () { + if (req.headers.authorization) { + let tokenData = services.getAccessTokens()[req.headers.authorization.split(' ').pop()]; + // console.log('App token data', tokenData) + + if (!tokenData || !tokenData.access_token) { + res.json({ code: HttpStatus.NOT_ACCEPTABLE }) + return false; + } + if (tokenData.expiresDate < new Date()) { + res.json({ code: HttpStatus.NOT_ACCEPTABLE }) + return false; + } + return true; + } + return false; + }()); + }); +} + + +app.use('/api/v1/headless', proxy('127.0.0.1:32101', { + filter: proxyFilter +})); + +app.use('/api/v1/spider', proxy('127.0.0.1:32102', { + filter: proxyFilter +})); + +app.use('/api/v1/spiduler', proxy('127.0.0.1:32103', { + filter: proxyFilter +})); + + + +app.get('/oauth/authorize', authorize) + +app.get('/api/v1/oauth/token', grantToken) +app.get('/oauth/token', grantToken) + +app.get('/api/test', apiEndpoint) + + + +app.listen(port) +console.log('Server starting port ' + port) \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..099f612 --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "name": "cm-auth", + "version": "1.0.0", + "description": "", + "main": "index.js", + "dependencies": { + "express": "^4.17.1", + "express-http-proxy": "^1.5.1", + "express-logging": "^1.1.1", + "http-status-codes": "^1.3.2", + "kgo": "^4.0.3", + "logops": "^2.1.1", + "lowdb": "^1.0.0", + "node-cron": "^2.0.3", + "node-uuid": "^1.4.8", + "simple-oauth-server": "^1.0.6" + }, + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node app/index.js" + }, + "author": "", + "license": "ISC" +} diff --git a/storage/db.json b/storage/db.json new file mode 100644 index 0000000..8d18147 --- /dev/null +++ b/storage/db.json @@ -0,0 +1,11 @@ +{ + "authCodes": [ + { + "code": "a9c6380a-9e34-467f-a1ae-514bb51a7724", + "redirectUri": "http://google.com", + "clientId": "F8Nbz9gGUvLgdn8T", + "expiresDate": null, + "accountId": "accountid" + } + ] +} \ No newline at end of file