mirror of
https://git.joinsharkey.org/Sharkey/Sharkey.git
synced 2025-01-08 15:53:09 +02:00
solve typescript warnings
This commit is contained in:
parent
b81e6eeff9
commit
260ac0ecfc
2 changed files with 43 additions and 18 deletions
|
@ -1,10 +1,11 @@
|
||||||
import dns from 'node:dns/promises';
|
import dns from 'node:dns/promises';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
|
import { ServerResponse } from 'node:http';
|
||||||
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';
|
||||||
import ipaddr from 'ipaddr.js';
|
import ipaddr from 'ipaddr.js';
|
||||||
import oauth2orize, { type OAuth2, AuthorizationError, ValidateFunctionArity2, OAuth2Req } from 'oauth2orize';
|
import oauth2orize, { type OAuth2, AuthorizationError, ValidateFunctionArity2, OAuth2Req, MiddlewareRequest } from 'oauth2orize';
|
||||||
import oauth2Pkce from 'oauth2orize-pkce';
|
import oauth2Pkce from 'oauth2orize-pkce';
|
||||||
import fastifyView from '@fastify/view';
|
import fastifyView from '@fastify/view';
|
||||||
import pug from 'pug';
|
import pug from 'pug';
|
||||||
|
@ -116,11 +117,23 @@ type OmitFirstElement<T extends unknown[]> = T extends [unknown, ...(infer R)]
|
||||||
? R
|
? R
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
interface OAuthRequest extends OAuth2Req {
|
interface OAuthParsedRequest extends OAuth2Req {
|
||||||
codeChallenge: string;
|
codeChallenge: string;
|
||||||
codeChallengeMethod: string;
|
codeChallengeMethod: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface OAuthHttpResponse extends ServerResponse {
|
||||||
|
redirect(location: string): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OAuth2DecisionRequest extends MiddlewareRequest {
|
||||||
|
body: {
|
||||||
|
transaction_id: string;
|
||||||
|
cancel: boolean;
|
||||||
|
login_token: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getQueryMode(issuerUrl: string): oauth2orize.grant.Options['modes'] {
|
function getQueryMode(issuerUrl: string): oauth2orize.grant.Options['modes'] {
|
||||||
return {
|
return {
|
||||||
query: (txn, res, params): void => {
|
query: (txn, res, params): void => {
|
||||||
|
@ -135,7 +148,7 @@ function getQueryMode(issuerUrl: string): oauth2orize.grant.Options['modes'] {
|
||||||
parsed.searchParams.append(key, value as string);
|
parsed.searchParams.append(key, value as string);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (res as any).redirect(parsed.toString());
|
return (res as OAuthHttpResponse).redirect(parsed.toString());
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -143,7 +156,7 @@ function getQueryMode(issuerUrl: string): oauth2orize.grant.Options['modes'] {
|
||||||
class OAuth2Store {
|
class OAuth2Store {
|
||||||
#cache = new MemoryKVCache<OAuth2>(1000 * 60 * 5); // 5min
|
#cache = new MemoryKVCache<OAuth2>(1000 * 60 * 5); // 5min
|
||||||
|
|
||||||
load(req: any, cb: (err: Error | null, txn?: OAuth2) => void): void {
|
load(req: OAuth2DecisionRequest, cb: (err: Error | null, txn?: OAuth2) => void): void {
|
||||||
const { transaction_id } = req.body;
|
const { transaction_id } = req.body;
|
||||||
if (!transaction_id) {
|
if (!transaction_id) {
|
||||||
cb(new AuthorizationError('Missing transaction ID', 'invalid_request'));
|
cb(new AuthorizationError('Missing transaction ID', 'invalid_request'));
|
||||||
|
@ -157,13 +170,13 @@ class OAuth2Store {
|
||||||
cb(null, loaded);
|
cb(null, loaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
store(req: unknown, oauth2: OAuth2, cb: (err: Error | null, transactionID?: string) => void): void {
|
store(req: OAuth2DecisionRequest, oauth2: OAuth2, cb: (err: Error | null, transactionID?: string) => void): void {
|
||||||
const transactionId = secureRndstr(128, true);
|
const transactionId = secureRndstr(128, true);
|
||||||
this.#cache.set(transactionId, oauth2);
|
this.#cache.set(transactionId, oauth2);
|
||||||
cb(null, transactionId);
|
cb(null, transactionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(req: unknown, tid: string, cb: () => void): void {
|
remove(req: OAuth2DecisionRequest, tid: string, cb: () => void): void {
|
||||||
this.#cache.delete(tid);
|
this.#cache.delete(tid);
|
||||||
cb();
|
cb();
|
||||||
}
|
}
|
||||||
|
@ -222,7 +235,7 @@ export class OAuth2ProviderService {
|
||||||
clientId: client.id,
|
clientId: client.id,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
redirectUri,
|
redirectUri,
|
||||||
codeChallenge: (areq as OAuthRequest).codeChallenge,
|
codeChallenge: (areq as OAuthParsedRequest).codeChallenge,
|
||||||
scopes: areq.scope,
|
scopes: areq.scope,
|
||||||
});
|
});
|
||||||
return [code];
|
return [code];
|
||||||
|
@ -285,7 +298,11 @@ export class OAuth2ProviderService {
|
||||||
// For now only allow the basic OAuth endpoints, to start small and evaluate
|
// For now only allow the basic OAuth endpoints, to start small and evaluate
|
||||||
// this feature for some time, given that this is security related.
|
// this feature for some time, given that this is security related.
|
||||||
fastify.get('/oauth/authorize', async (request, reply) => {
|
fastify.get('/oauth/authorize', async (request, reply) => {
|
||||||
const oauth2 = (request.raw as any).oauth2 as OAuth2;
|
const oauth2 = (request.raw as MiddlewareRequest).oauth2;
|
||||||
|
if (!oauth2) {
|
||||||
|
throw new Error('Unexpected lack of authorization information');
|
||||||
|
}
|
||||||
|
|
||||||
this.#logger.info(`Rendering authorization page for "${oauth2.client.name}"`);
|
this.#logger.info(`Rendering authorization page for "${oauth2.client.name}"`);
|
||||||
|
|
||||||
reply.header('Cache-Control', 'no-store');
|
reply.header('Cache-Control', 'no-store');
|
||||||
|
@ -313,7 +330,7 @@ export class OAuth2ProviderService {
|
||||||
// This should return client/redirectURI AND the error, or
|
// This should return client/redirectURI AND the error, or
|
||||||
// the handler can't send error to the redirection URI
|
// the handler can't send error to the redirection URI
|
||||||
|
|
||||||
const { codeChallenge, codeChallengeMethod, clientID, redirectURI, scope, type } = areq as OAuthRequest;
|
const { codeChallenge, codeChallengeMethod, clientID, redirectURI, scope, type } = areq as OAuthParsedRequest;
|
||||||
|
|
||||||
this.#logger.info(`Validating authorization parameters, with client_id: ${clientID}, redirect_uri: ${redirectURI}, scope: ${scope}`);
|
this.#logger.info(`Validating authorization parameters, with client_id: ${clientID}, redirect_uri: ${redirectURI}, scope: ${scope}`);
|
||||||
|
|
||||||
|
@ -367,8 +384,9 @@ export class OAuth2ProviderService {
|
||||||
|
|
||||||
fastify.use('/oauth/decision', bodyParser.urlencoded({ extended: false }));
|
fastify.use('/oauth/decision', bodyParser.urlencoded({ extended: false }));
|
||||||
fastify.use('/oauth/decision', this.#server.decision((req, done) => {
|
fastify.use('/oauth/decision', this.#server.decision((req, done) => {
|
||||||
this.#logger.info(`Received the decision. Cancel: ${!!(req as any).body.cancel}`);
|
const { body } = req as OAuth2DecisionRequest;
|
||||||
req.user = (req as any).body.login_token;
|
this.#logger.info(`Received the decision. Cancel: ${!!body.cancel}`);
|
||||||
|
req.user = body.login_token;
|
||||||
done(null, undefined);
|
done(null, undefined);
|
||||||
}));
|
}));
|
||||||
fastify.use('/oauth/decision', this.#server.errorHandler());
|
fastify.use('/oauth/decision', this.#server.errorHandler());
|
||||||
|
|
|
@ -224,7 +224,7 @@ describe('OAuth', () => {
|
||||||
});
|
});
|
||||||
assert.strictEqual(createResponse.status, 200);
|
assert.strictEqual(createResponse.status, 200);
|
||||||
|
|
||||||
const createResponseBody: any = await createResponse.json();
|
const createResponseBody = await createResponse.json() as { createdNote: Note };
|
||||||
assert.strictEqual(createResponseBody.createdNote.text, 'test');
|
assert.strictEqual(createResponseBody.createdNote.text, 'test');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -258,20 +258,27 @@ describe('OAuth', () => {
|
||||||
const decisionResponseBob = await fetchDecisionFromResponse(responseBob, bob);
|
const decisionResponseBob = await fetchDecisionFromResponse(responseBob, bob);
|
||||||
assert.strictEqual(decisionResponseBob.status, 302);
|
assert.strictEqual(decisionResponseBob.status, 302);
|
||||||
|
|
||||||
const locationAlice = new URL(decisionResponseAlice.headers.get('location')!);
|
const locationHeaderAlice = decisionResponseAlice.headers.get('location');
|
||||||
assert.ok(locationAlice.searchParams.has('code'));
|
assert.ok(locationHeaderAlice);
|
||||||
|
const locationAlice = new URL(locationHeaderAlice);
|
||||||
|
|
||||||
const locationBob = new URL(decisionResponseBob.headers.get('location')!);
|
const locationHeaderBob = decisionResponseBob.headers.get('location');
|
||||||
assert.ok(locationBob.searchParams.has('code'));
|
assert.ok(locationHeaderBob);
|
||||||
|
const locationBob = new URL(locationHeaderBob);
|
||||||
|
|
||||||
|
const codeAlice = locationAlice.searchParams.get('code');
|
||||||
|
assert.ok(codeAlice);
|
||||||
|
const codeBob = locationBob.searchParams.get('code');
|
||||||
|
assert.ok(codeBob);
|
||||||
|
|
||||||
const tokenAlice = await client.getToken({
|
const tokenAlice = await client.getToken({
|
||||||
code: locationAlice.searchParams.get('code')!,
|
code: codeAlice,
|
||||||
redirect_uri,
|
redirect_uri,
|
||||||
code_verifier: pkceAlice.code_verifier,
|
code_verifier: pkceAlice.code_verifier,
|
||||||
} as AuthorizationTokenConfigExtended);
|
} as AuthorizationTokenConfigExtended);
|
||||||
|
|
||||||
const tokenBob = await client.getToken({
|
const tokenBob = await client.getToken({
|
||||||
code: locationBob.searchParams.get('code')!,
|
code: codeBob,
|
||||||
redirect_uri,
|
redirect_uri,
|
||||||
code_verifier: pkceBob.code_verifier,
|
code_verifier: pkceBob.code_verifier,
|
||||||
} as AuthorizationTokenConfigExtended);
|
} as AuthorizationTokenConfigExtended);
|
||||||
|
|
Loading…
Reference in a new issue