From 56cb70ee847bd511c5a925dbad3e495f22126c7c Mon Sep 17 00:00:00 2001 From: ha-dai Date: Thu, 5 Jan 2017 21:58:02 +0900 Subject: Improve convenience. --- src/api/endpoints/users/posts.js | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'src/api/endpoints') diff --git a/src/api/endpoints/users/posts.js b/src/api/endpoints/users/posts.js index 6d6f8a6904..e1a59efa2f 100644 --- a/src/api/endpoints/users/posts.js +++ b/src/api/endpoints/users/posts.js @@ -20,8 +20,18 @@ module.exports = (params, me) => { // Get 'user_id' parameter const userId = params.user_id; - if (userId === undefined || userId === null) { - return rej('user_id is required'); + if (userId === undefined || userId === null || userId === '') { + userId = null; + } + + // Get 'username' parameter + const username = params.username; + if (username === undefined || username === null || username === '') { + username = null; + } + + if (userId === null && username === null) { + return rej('user_id or username is required'); } // Get 'with_replies' parameter @@ -62,9 +72,9 @@ module.exports = (params, me) => } // Lookup user - const user = await User.findOne({ - _id: new mongo.ObjectID(userId) - }); + const user = userId !== null + ? await User.findOne({ _id: new mongo.ObjectID(userId) }) + : await User.findOne({ username_lower: username.toLowerCase() }); if (user === null) { return rej('user not found'); -- cgit v1.2.3-freya From a63de6d776d6f9f7840555a86fa0af05e173bc91 Mon Sep 17 00:00:00 2001 From: syuilo⭐️ Date: Thu, 5 Jan 2017 22:15:53 +0900 Subject: Fix bug Use `let` instead of `const` --- src/api/endpoints/users/posts.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/api/endpoints') diff --git a/src/api/endpoints/users/posts.js b/src/api/endpoints/users/posts.js index e1a59efa2f..1b8dfe031b 100644 --- a/src/api/endpoints/users/posts.js +++ b/src/api/endpoints/users/posts.js @@ -19,13 +19,13 @@ module.exports = (params, me) => new Promise(async (res, rej) => { // Get 'user_id' parameter - const userId = params.user_id; + let userId = params.user_id; if (userId === undefined || userId === null || userId === '') { userId = null; } // Get 'username' parameter - const username = params.username; + let username = params.username; if (username === undefined || username === null || username === '') { username = null; } -- cgit v1.2.3-freya From 94582453820655d11cb6dff8ad62148742591103 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 6 Jan 2017 11:50:46 +0900 Subject: [BREAKING CHANGE] Improve security --- docs/api/getting-started.pug | 2 ++ package.json | 1 + src/api/authenticate.ts | 2 +- src/api/endpoints/auth/accept.js | 15 ++++++++++++++- src/api/streaming.ts | 2 +- 5 files changed, 19 insertions(+), 3 deletions(-) (limited to 'src/api/endpoints') diff --git a/docs/api/getting-started.pug b/docs/api/getting-started.pug index f565745232..e255a5e935 100644 --- a/docs/api/getting-started.pug +++ b/docs/api/getting-started.pug @@ -70,5 +70,7 @@ block content | 次に、#{api_url}/auth/session/userkeyapp_secretとしてApp Secretを、tokenとしてセッションのトークンをパラメータとして付与したリクエストを送信してください。 br | 上手くいけば、認証したユーザーのアクセストークンがレスポンスとして取得できます。おめでとうございます! + p + | 以降アクセストークンは、ユーザーのアクセストークン+アプリのシークレットキーをsha512したものとして扱います。 p アクセストークンを取得できたら、あとは簡単です。REST APIなら、リクエストにアクセストークンをiとしてパラメータに含めるだけです。 diff --git a/package.json b/package.json index 423103c75d..1debc88538 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "compression": "1.6.2", "cors": "2.8.1", "cropperjs": "1.0.0-beta", + "crypto": "0.0.3", "deepcopy": "0.6.3", "del": "2.2.2", "elasticsearch": "12.1.3", diff --git a/src/api/authenticate.ts b/src/api/authenticate.ts index 832517379f..0a888e72d3 100644 --- a/src/api/authenticate.ts +++ b/src/api/authenticate.ts @@ -43,7 +43,7 @@ export default (req: express.Request) => new Promise(async (resolv }); } else { const userkeyDoc = await Userkey.findOne({ - key: token + hash: token }); if (userkeyDoc === null) { diff --git a/src/api/endpoints/auth/accept.js b/src/api/endpoints/auth/accept.js index 7c45650c6b..9eb5d2e7e2 100644 --- a/src/api/endpoints/auth/accept.js +++ b/src/api/endpoints/auth/accept.js @@ -4,6 +4,8 @@ * Module dependencies */ import rndstr from 'rndstr'; +const crypto = require('crypto'); +import App from '../../models/app'; import AuthSess from '../../models/auth-session'; import Userkey from '../../models/userkey'; @@ -41,12 +43,23 @@ module.exports = (params, user) => }); if (exist === null) { + // Lookup app + const app = await App.findOne({ + app_id: session.app_id + }); + + // Generate Hash + const sha512 = crypto.createHash('sha512'); + sha512.update(key + app.secret); + const hash = sha512.digest('hex'); + // Insert userkey doc await Userkey.insert({ created_at: new Date(), app_id: session.app_id, user_id: user._id, - key: key + key: key, + hash: hash }); } diff --git a/src/api/streaming.ts b/src/api/streaming.ts index 84a0f9ddf4..dd28a0bc1e 100644 --- a/src/api/streaming.ts +++ b/src/api/streaming.ts @@ -64,7 +64,7 @@ function authenticate(connection: websocket.connection, token: string): Promise< resolve(user); } else { const userkey = await Userkey.findOne({ - key: token + hash: token }); if (userkey == null) { -- cgit v1.2.3-freya From fef3d3f300c80bf26b0c6a203db5782f76463151 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 6 Jan 2017 12:09:57 +0900 Subject: Refactor: Rename userkey --> access-token --- src/api/authenticate.ts | 12 ++++++------ src/api/endpoints/auth/accept.js | 24 ++++++++++++------------ src/api/endpoints/auth/session/userkey.js | 8 ++++---- src/api/models/access-token.ts | 6 ++++++ src/api/models/userkey.ts | 5 ----- src/api/serializers/app.ts | 4 ++-- src/api/streaming.ts | 10 +++++----- 7 files changed, 35 insertions(+), 34 deletions(-) create mode 100644 src/api/models/access-token.ts delete mode 100644 src/api/models/userkey.ts (limited to 'src/api/endpoints') diff --git a/src/api/authenticate.ts b/src/api/authenticate.ts index 0a888e72d3..2304acff21 100644 --- a/src/api/authenticate.ts +++ b/src/api/authenticate.ts @@ -1,7 +1,7 @@ import * as express from 'express'; import App from './models/app'; import User from './models/user'; -import Userkey from './models/userkey'; +import AccessToken from './models/access-token'; import isNativeToken from './common/is-native-token'; export interface IAuthContext { @@ -42,19 +42,19 @@ export default (req: express.Request) => new Promise(async (resolv isSecure: true }); } else { - const userkeyDoc = await Userkey.findOne({ + const accessToken = await AccessToken.findOne({ hash: token }); - if (userkeyDoc === null) { - return reject('invalid userkey'); + if (accessToken === null) { + return reject('invalid token'); } const app = await App - .findOne({ _id: userkeyDoc.app_id }); + .findOne({ _id: accessToken.app_id }); const user = await User - .findOne({ _id: userkeyDoc.user_id }); + .findOne({ _id: accessToken.user_id }); return resolve({ app: app, user: user, isSecure: false }); } diff --git a/src/api/endpoints/auth/accept.js b/src/api/endpoints/auth/accept.js index 9eb5d2e7e2..110a0897df 100644 --- a/src/api/endpoints/auth/accept.js +++ b/src/api/endpoints/auth/accept.js @@ -7,7 +7,7 @@ import rndstr from 'rndstr'; const crypto = require('crypto'); import App from '../../models/app'; import AuthSess from '../../models/auth-session'; -import Userkey from '../../models/userkey'; +import AccessToken from '../../models/access-token'; /** * Accept @@ -20,24 +20,24 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Get 'token' parameter - const token = params.token; - if (token == null) { + const sesstoken = params.token; + if (sesstoken == null) { return rej('token is required'); } // Fetch token const session = await AuthSess - .findOne({ token: token }); + .findOne({ token: sesstoken }); if (session === null) { return rej('session not found'); } - // Generate userkey - const key = rndstr('a-zA-Z0-9', 32); + // Generate access token + const token = rndstr('a-zA-Z0-9', 32); - // Fetch exist userkey - const exist = await Userkey.findOne({ + // Fetch exist access token + const exist = await AccessToken.findOne({ app_id: session.app_id, user_id: user._id, }); @@ -50,15 +50,15 @@ module.exports = (params, user) => // Generate Hash const sha512 = crypto.createHash('sha512'); - sha512.update(key + app.secret); + sha512.update(token + app.secret); const hash = sha512.digest('hex'); - // Insert userkey doc - await Userkey.insert({ + // Insert access token doc + await AccessToken.insert({ created_at: new Date(), app_id: session.app_id, user_id: user._id, - key: key, + token: token, hash: hash }); } diff --git a/src/api/endpoints/auth/session/userkey.js b/src/api/endpoints/auth/session/userkey.js index 2626e4ce39..f85a720ea4 100644 --- a/src/api/endpoints/auth/session/userkey.js +++ b/src/api/endpoints/auth/session/userkey.js @@ -5,7 +5,7 @@ */ import App from '../../../models/app'; import AuthSess from '../../../models/auth-session'; -import Userkey from '../../../models/userkey'; +import AccessToken from '../../../models/access-token'; import serialize from '../../../serializers/user'; /** @@ -53,8 +53,8 @@ module.exports = (params) => return rej('this session is not allowed yet'); } - // Lookup userkey - const userkey = await Userkey.findOne({ + // Lookup access token + const accessToken = await AccessToken.findOne({ app_id: app._id, user_id: session.user_id }); @@ -66,7 +66,7 @@ module.exports = (params) => // Response res({ - userkey: userkey.key, + access_token: accessToken.token, user: await serialize(session.user_id, null, { detail: true }) diff --git a/src/api/models/access-token.ts b/src/api/models/access-token.ts new file mode 100644 index 0000000000..f94df954d6 --- /dev/null +++ b/src/api/models/access-token.ts @@ -0,0 +1,6 @@ +const collection = global.db.collection('access_tokens'); + +collection.createIndex('token'); +collection.createIndex('hash'); + +export default collection; diff --git a/src/api/models/userkey.ts b/src/api/models/userkey.ts deleted file mode 100644 index 204f283a28..0000000000 --- a/src/api/models/userkey.ts +++ /dev/null @@ -1,5 +0,0 @@ -const collection = global.db.collection('userkeys'); - -collection.createIndex('key'); - -export default collection; diff --git a/src/api/serializers/app.ts b/src/api/serializers/app.ts index 1c4b244a36..b60bcb97e6 100644 --- a/src/api/serializers/app.ts +++ b/src/api/serializers/app.ts @@ -7,7 +7,7 @@ import * as mongo from 'mongodb'; import deepcopy = require('deepcopy'); import App from '../models/app'; import User from '../models/user'; -import Userkey from '../models/userkey'; +import AccessToken from '../models/access-token'; /** * Serialize an app @@ -71,7 +71,7 @@ export default ( if (me) { // 既に連携しているか - const exist = await Userkey.count({ + const exist = await AccessToken.count({ app_id: _app.id, user_id: me, }, { diff --git a/src/api/streaming.ts b/src/api/streaming.ts index dd28a0bc1e..49269ac445 100644 --- a/src/api/streaming.ts +++ b/src/api/streaming.ts @@ -2,7 +2,7 @@ import * as http from 'http'; import * as websocket from 'websocket'; import * as redis from 'redis'; import User from './models/user'; -import Userkey from './models/userkey'; +import AccessToken from './models/access-token'; import isNativeToken from './common/is-native-token'; import homeStream from './stream/home'; @@ -63,18 +63,18 @@ function authenticate(connection: websocket.connection, token: string): Promise< resolve(user); } else { - const userkey = await Userkey.findOne({ + const accessToken = await AccessToken.findOne({ hash: token }); - if (userkey == null) { - return reject('invalid userkey'); + if (accessToken == null) { + return reject('invalid token'); } // Fetch user // SELECT _id const user = await User - .findOne({ _id: userkey.user_id }, { + .findOne({ _id: accessToken.user_id }, { _id: true }); -- cgit v1.2.3-freya