diff options
| author | Tosuke <tasukeprg@gmail.com> | 2017-01-06 14:39:24 +0900 |
|---|---|---|
| committer | Tosuke <tasukeprg@gmail.com> | 2017-01-06 14:39:24 +0900 |
| commit | 0420fee5d2c6a944a7b2cf13307dfadce9796b59 (patch) | |
| tree | d8c361b2c340c03927a5a417e5a91b3ab58db34b /src/api | |
| parent | [Swagger]Add /auth/accept (diff) | |
| parent | Update changelog (diff) | |
| download | sharkey-0420fee5d2c6a944a7b2cf13307dfadce9796b59.tar.gz sharkey-0420fee5d2c6a944a7b2cf13307dfadce9796b59.tar.bz2 sharkey-0420fee5d2c6a944a7b2cf13307dfadce9796b59.zip | |
Merge branch 'master' of github.com:syuilo/misskey into swagger
Diffstat (limited to 'src/api')
| -rw-r--r-- | src/api/authenticate.ts | 32 | ||||
| -rw-r--r-- | src/api/common/is-native-token.ts | 1 | ||||
| -rw-r--r-- | src/api/endpoints/auth/accept.js | 35 | ||||
| -rw-r--r-- | src/api/endpoints/auth/session/userkey.js | 8 | ||||
| -rw-r--r-- | src/api/endpoints/users/posts.js | 22 | ||||
| -rw-r--r-- | src/api/models/access-token.ts | 6 | ||||
| -rw-r--r-- | src/api/models/userkey.ts | 5 | ||||
| -rw-r--r-- | src/api/private/signup.ts | 2 | ||||
| -rw-r--r-- | src/api/serializers/app.ts | 4 | ||||
| -rw-r--r-- | src/api/streaming.ts | 41 |
10 files changed, 98 insertions, 58 deletions
diff --git a/src/api/authenticate.ts b/src/api/authenticate.ts index 5798adb83d..50a55e51b7 100644 --- a/src/api/authenticate.ts +++ b/src/api/authenticate.ts @@ -1,7 +1,8 @@ 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 { /** @@ -20,10 +21,14 @@ export interface IAuthContext { isSecure: boolean; } -export default (req: express.Request) => - new Promise<IAuthContext>(async (resolve, reject) => { +export default (req: express.Request) => new Promise<IAuthContext>(async (resolve, reject) => { const token = req.body['i']; - if (token) { + + if (token == null) { + return resolve({ app: null, user: null, isSecure: false }); + } + + if (isNativeToken(token)) { const user = await User .findOne({ token: token }); @@ -36,26 +41,21 @@ export default (req: express.Request) => user: user, isSecure: true }); - } - - const userkey = req.headers['userkey'] || req.body['_userkey']; - if (userkey) { - const userkeyDoc = await Userkey.findOne({ - key: userkey + } else { + const accessToken = await AccessToken.findOne({ + hash: token }); - if (userkeyDoc === null) { - return reject('invalid userkey'); + if (accessToken === null) { + return reject('invalid signature'); } 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 }); } - - return resolve({ app: null, user: null, isSecure: false }); }); diff --git a/src/api/common/is-native-token.ts b/src/api/common/is-native-token.ts new file mode 100644 index 0000000000..0769a4812e --- /dev/null +++ b/src/api/common/is-native-token.ts @@ -0,0 +1 @@ +export default (token: string) => token[0] == '!'; diff --git a/src/api/endpoints/auth/accept.js b/src/api/endpoints/auth/accept.js index e584513c05..d60d95aea3 100644 --- a/src/api/endpoints/auth/accept.js +++ b/src/api/endpoints/auth/accept.js @@ -4,8 +4,10 @@ * 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'; +import AccessToken from '../../models/access-token'; /** * @swagger @@ -41,35 +43,46 @@ 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, }); if (exist === null) { - // Insert userkey doc - await Userkey.insert({ + // Lookup app + const app = await App.findOne({ + app_id: session.app_id + }); + + // Generate Hash + const sha512 = crypto.createHash('sha512'); + sha512.update(token + app.secret); + const hash = sha512.digest('hex'); + + // 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 73fa643c9c..9252046e57 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'; /** @@ -89,8 +89,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 }); @@ -102,7 +102,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/endpoints/users/posts.js b/src/api/endpoints/users/posts.js index 6d6f8a6904..1b8dfe031b 100644 --- a/src/api/endpoints/users/posts.js +++ b/src/api/endpoints/users/posts.js @@ -19,9 +19,19 @@ module.exports = (params, me) => new Promise(async (res, rej) => { // Get 'user_id' parameter - const userId = params.user_id; - if (userId === undefined || userId === null) { - return rej('user_id is required'); + let userId = params.user_id; + if (userId === undefined || userId === null || userId === '') { + userId = null; + } + + // Get 'username' parameter + let 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'); 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/private/signup.ts b/src/api/private/signup.ts index c50b070052..592dfcceb1 100644 --- a/src/api/private/signup.ts +++ b/src/api/private/signup.ts @@ -48,7 +48,7 @@ export default async (req: express.Request, res: express.Response) => { const hash = bcrypt.hashSync(password, salt); // Generate secret - const secret = rndstr('a-zA-Z0-9', 32); + const secret = '!' + rndstr('a-zA-Z0-9', 32); // Create account const inserted = await User.insert({ 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 38068d1e3d..7a8d2d4354 100644 --- a/src/api/streaming.ts +++ b/src/api/streaming.ts @@ -2,6 +2,8 @@ import * as http from 'http'; import * as websocket from 'websocket'; import * as redis from 'redis'; import User from './models/user'; +import AccessToken from './models/access-token'; +import isNativeToken from './common/is-native-token'; import homeStream from './stream/home'; import messagingStream from './stream/messaging'; @@ -17,7 +19,13 @@ module.exports = (server: http.Server) => { ws.on('request', async (request) => { const connection = request.accept(); - const user = await authenticate(connection); + const user = await authenticate(connection, request.resourceURL.query.i); + + if (user == null) { + connection.send('authentication-failed'); + connection.close(); + return; + } // Connect to Redis const subscriber = redis.createClient( @@ -41,29 +49,36 @@ module.exports = (server: http.Server) => { }); }; -function authenticate(connection: websocket.connection): Promise<any> { - return new Promise((resolve, reject) => { - // Listen first message - connection.once('message', async (data) => { - const msg = JSON.parse(data.utf8Data); - +function authenticate(connection: websocket.connection, token: string): Promise<any> { + return new Promise(async (resolve, reject) => { + if (isNativeToken(token)) { // Fetch user // SELECT _id const user = await User .findOne({ - token: msg.i + token: token }, { _id: true }); - if (user === null) { - connection.close(); - return; + resolve(user); + } else { + const accessToken = await AccessToken.findOne({ + hash: token + }); + + if (accessToken == null) { + return reject('invalid signature'); } - connection.send('authenticated'); + // Fetch user + // SELECT _id + const user = await User + .findOne({ _id: accessToken.user_id }, { + _id: true + }); resolve(user); - }); + } }); } |