Use MemoryKVCache

This commit is contained in:
Kagami Sascha Rosylight 2023-05-27 20:52:48 +02:00
parent c0f63234d7
commit 150a6f80d0

View file

@ -1,6 +1,5 @@
import dns from 'node:dns/promises'; import dns from 'node:dns/promises';
import { fileURLToPath } from 'node:url'; import { fileURLToPath } from 'node:url';
import crypto from 'node:crypto';
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { JSDOM } from 'jsdom'; import { JSDOM } from 'jsdom';
import httpLinkHeader from 'http-link-header'; import httpLinkHeader from 'http-link-header';
@ -24,6 +23,7 @@ import type { AccessTokensRepository, UsersRepository } from '@/models/index.js'
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
import { CacheService } from '@/core/CacheService.js'; import { CacheService } from '@/core/CacheService.js';
import type { LocalUser } from '@/models/entities/User.js'; import type { LocalUser } from '@/models/entities/User.js';
import { MemoryKVCache } from '@/misc/cache.js';
import type * as Redis from 'ioredis'; import type * as Redis from 'ioredis';
import type { FastifyInstance } from 'fastify'; import type { FastifyInstance } from 'fastify';
@ -304,14 +304,14 @@ export class OAuth2ProviderService {
// }, // },
// }); // });
// TODO: store this in Redis // XXX: But MemoryKVCache just grows forever without being cleared...
const TEMP_GRANT_CODES: Record<string, { const grantCodeCache = new MemoryKVCache<{
clientId: string, clientId: string,
userId: string, userId: string,
redirectUri: string, redirectUri: string,
codeChallenge: string, codeChallenge: string,
scopes: string[], scopes: string[],
}> = {}; }>(1000 * 60 * 5); // 5m
this.#server.grant(oauth2Pkce.extensions()); this.#server.grant(oauth2Pkce.extensions());
this.#server.grant(oauth2orize.grant.code({ this.#server.grant(oauth2orize.grant.code({
@ -339,25 +339,24 @@ export class OAuth2ProviderService {
throw new AuthorizationError('No such user', 'invalid_request'); throw new AuthorizationError('No such user', 'invalid_request');
} }
TEMP_GRANT_CODES[code] = { grantCodeCache.set(code, {
clientId: client.id, clientId: client.id,
userId: user.id, userId: user.id,
redirectUri, redirectUri,
codeChallenge: (areq as OAuthRequest).codeChallenge, codeChallenge: (areq as OAuthRequest).codeChallenge,
scopes: areq.scope, scopes: areq.scope,
}; });
return [code]; return [code];
})().then(args => done(null, ...args), err => done(err)); })().then(args => done(null, ...args), err => done(err));
})); }));
this.#server.exchange(oauth2orize.exchange.authorizationCode((client, code, redirectUri, body, authInfo, done) => { this.#server.exchange(oauth2orize.exchange.authorizationCode((client, code, redirectUri, body, authInfo, done) => {
(async (): Promise<OmitFirstElement<Parameters<typeof done>>> => { (async (): Promise<OmitFirstElement<Parameters<typeof done>>> => {
const granted = TEMP_GRANT_CODES[code]; const granted = grantCodeCache.get(code);
console.log(granted, body, code, redirectUri); console.log(granted, body, code, redirectUri);
if (!granted) { if (!granted) {
// TODO: throw TokenError?
return [false]; return [false];
} }
delete TEMP_GRANT_CODES[code]; grantCodeCache.delete(code);
if (body.client_id !== granted.clientId) return [false]; if (body.client_id !== granted.clientId) return [false];
if (redirectUri !== granted.redirectUri) return [false]; if (redirectUri !== granted.redirectUri) return [false];
if (!body.code_verifier) return [false]; if (!body.code_verifier) return [false];