Handle upstream tokens more safely

This commit is contained in:
Travis Ralston 2019-04-17 23:34:14 -06:00
parent 109bceb924
commit be66dd04f9
8 changed files with 36 additions and 7 deletions

View file

@ -33,7 +33,7 @@ export class ScalarService {
* @returns {Promise<string>} Resolves to the owner's user ID if the token is valid. * @returns {Promise<string>} Resolves to the owner's user ID if the token is valid.
* @throws {ApiError} Thrown with a status code of 401 if the token is invalid. * @throws {ApiError} Thrown with a status code of 401 if the token is invalid.
*/ */
public static async getTokenOwner(scalarToken: string, ignoreUpstreams?: boolean): Promise<string> { public static async getTokenOwner(scalarToken: string, ignoreUpstreams = false): Promise<string> {
const cachedUserId = Cache.for(CACHE_SCALAR_ACCOUNTS).get(scalarToken); const cachedUserId = Cache.for(CACHE_SCALAR_ACCOUNTS).get(scalarToken);
if (cachedUserId) return cachedUserId; if (cachedUserId) return cachedUserId;

View file

@ -150,7 +150,7 @@ export class NebStore {
const botUserId = null; // TODO: For github const botUserId = null; // TODO: For github
const botConfig = await proxy.getServiceConfiguration(i.integration, roomId); const botConfig = await proxy.getServiceConfiguration(i.integration, roomId);
const bot = new ComplexBot(i.integration, notifUserId, botUserId, botConfig); const bot = new ComplexBot(i.integration, notifUserId, botUserId, botConfig);
bot.isOnline = !!bot.botUserId; bot.isOnline = !!bot.notificationUserId;
return bot; return bot;
} catch (e) { } catch (e) {
LogService.error("NebStore", e); LogService.error("NebStore", e);

View file

@ -33,7 +33,7 @@ export class ScalarStore {
return true; return true;
} }
public static async getTokenOwner(scalarToken: string, ignoreUpstreams?: boolean): Promise<User> { public static async getTokenOwner(scalarToken: string, ignoreUpstreams = false): Promise<User> {
const tokens = await UserScalarToken.findAll({ const tokens = await UserScalarToken.findAll({
where: {isDimensionToken: true, scalarToken: scalarToken}, where: {isDimensionToken: true, scalarToken: scalarToken},
include: [User] include: [User]
@ -104,6 +104,14 @@ export class ScalarStore {
} }
} }
const user = await User.findByPk(testUserId);
if (!user) {
await User.create({
userId: testUserId,
isSelfBot: true,
});
}
const openId = await MatrixStickerBot.getOpenId(); const openId = await MatrixStickerBot.getOpenId();
const token = await scalarClient.register(openId); const token = await scalarClient.register(openId);
await UserScalarToken.create({ await UserScalarToken.create({

View file

@ -0,0 +1,17 @@
import { QueryInterface } from "sequelize";
import { DataType } from "sequelize-typescript";
export default {
up: (queryInterface: QueryInterface) => {
return Promise.resolve()
.then(() => queryInterface.addColumn("dimension_users", "isSelfBot", {
type: DataType.BOOLEAN,
allowNull: false,
defaultValue: false,
}));
},
down: (queryInterface: QueryInterface) => {
return Promise.resolve()
.then(() => queryInterface.removeColumn("dimension_users", "isSelfBot"));
}
}

View file

@ -11,4 +11,7 @@ export default class User extends Model<User> {
@PrimaryKey @PrimaryKey
@Column @Column
userId: string; userId: string;
@Column
isSelfBot: boolean;
} }

View file

@ -4,8 +4,8 @@ import { DimensionStore } from "./db/DimensionStore";
import Webserver from "./api/Webserver"; import Webserver from "./api/Webserver";
import { CURRENT_VERSION } from "./version"; import { CURRENT_VERSION } from "./version";
import { MatrixStickerBot } from "./matrix/MatrixStickerBot"; import { MatrixStickerBot } from "./matrix/MatrixStickerBot";
import UserScalarToken from "./db/models/UserScalarToken";
import * as BotSdk from "matrix-bot-sdk"; import * as BotSdk from "matrix-bot-sdk";
import User from "./db/models/User";
LogService.configure(config.logging); LogService.configure(config.logging);
LogService.info("index", "Starting dimension " + CURRENT_VERSION); LogService.info("index", "Starting dimension " + CURRENT_VERSION);
@ -25,8 +25,8 @@ async function startup() {
await webserver.start(); await webserver.start();
const userId = await MatrixStickerBot.getUserId(); const userId = await MatrixStickerBot.getUserId();
const tokens = await UserScalarToken.findAll({where: {userId: userId}}); const users = await User.findAll({where: {userId: userId, isSelfBot: false}});
if (tokens.length > 0) { if (users.length > 0) {
LogService.error("index", "The access token configured for Dimension belongs to a user which is also " + LogService.error("index", "The access token configured for Dimension belongs to a user which is also " +
"a user known to Dimension. This usually indicates that the access token is not a dedicated user " + "a user known to Dimension. This usually indicates that the access token is not a dedicated user " +
"account for Dimension. To prevent potential confusion to this user, Dimension will refuse to start " + "account for Dimension. To prevent potential confusion to this user, Dimension will refuse to start " +

View file

@ -49,7 +49,7 @@ export class MatrixLiteClient {
return await doClientApiCall( return await doClientApiCall(
"POST", "POST",
`/_matrix/client/r0/user/${await this.whoAmI()}/openid/request_token`, `/_matrix/client/r0/user/${await this.whoAmI()}/openid/request_token`,
{access_token: this.accessToken}, {access_token: this.accessToken}, {},
); );
} }

View file

@ -39,6 +39,7 @@ export class ScalarClient {
method: "GET", method: "GET",
url: this.upstream.scalarUrl + "/account", url: this.upstream.scalarUrl + "/account",
qs: {v: SCALAR_API_VERSION, scalar_token: token}, qs: {v: SCALAR_API_VERSION, scalar_token: token},
json: true,
}, (err, res, _body) => { }, (err, res, _body) => {
if (err) { if (err) {
LogService.error("ScalarClient", "Error getting information for token"); LogService.error("ScalarClient", "Error getting information for token");