From cc47c52a9de4a605cd07b30bc9db60e5979a0954 Mon Sep 17 00:00:00 2001 From: rob Date: Wed, 20 Jul 2022 18:21:42 -0400 Subject: [PATCH] verifyKaleidoscopeToken and support --- app/services/oauth2.js | 45 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/app/services/oauth2.js b/app/services/oauth2.js index 1f00130..00f0820 100644 --- a/app/services/oauth2.js +++ b/app/services/oauth2.js @@ -57,6 +57,7 @@ class OAuth2Service extends SiteService { registerPassport ( ) { const verifyClient = this.verifyClient.bind(this); const verifyHttpBearer = this.verifyHttpBearer.bind(this); + const verifyKaleidoscopeBearer = this.verifyKaleidoscopeBearer.bind(this); const basicStrategy = new BasicStrategy(verifyClient); this.log.info('registering Basic strategy', { name: basicStrategy.name }); @@ -69,6 +70,10 @@ class OAuth2Service extends SiteService { const httpBearerStrategy = new BearerStrategy(verifyHttpBearer); this.log.info('registering Bearer strategy', { name: httpBearerStrategy.name }); passport.use(httpBearerStrategy); + + const kaleidoscopeBearerStrategy = new BearerStrategy(verifyKaleidoscopeBearer); + this.log.info('registering Kaleidoscope Bearer strategy'); + passport.use(kaleidoscopeBearerStrategy); } async serializeClient (client, done) { @@ -392,6 +397,7 @@ class OAuth2Service extends SiteService { async verifyHttpBearer (accessToken, done) { const token = await this.getAccessToken(accessToken); if (!token) { + this.log.error('no bearer token for client', { accessToken }); return done(null, false); } return done(null, token.user, { scope: token.scope }); @@ -411,6 +417,45 @@ class OAuth2Service extends SiteService { .lean(); return tokens; } + + async getKaleidoscopeClient (accessToken) { + const client = await OAuth2Client + .findOne({ 'kaleidoscope.token': accessToken }) + .select('-secret -kaleidoscope -admin') // don't fetch them + .lean(); + if (!client) { + return; // we don't have one, be undefined + } + /* + * extreme paranoia also serializes the object to absolutely prevent leaking + * a secret even if the underlying Mongoose library has a bug today. + */ + return { + _id: client._id, + created: client.created, + updated: client.updated, + site: client.site, + scopes: client.scopes, + flags: client.flags, + }; + } + + async verifyKaleidoscopeBearer (accessToken, done) { + const client = await this.getKaleidoscopeClient(accessToken); + if (!client) { + this.log.error('no Kaleidoscope token for client', { accessToken }); + return done(null, false); + } + /* + * Minor hack here. You don't get a User or CoreUser for use with + * Kaleidoscope. This is machine-to-machine, there simply is no "user" in + * this transaction. Instead, you get a Client - the machine. + * + * So, up in controller space, req.user isn't a User or CoreUser for + * Kaleidoscope APIs. It is the OAuth2 Client or Service Node. + */ + return done(null, client); + } } module.exports = {