From 763e0cdf11a73106d30593a9f2d7ebb021ef1a29 Mon Sep 17 00:00:00 2001 From: Nevo David Date: Thu, 12 Dec 2024 23:41:04 +0700 Subject: [PATCH] feat: prevent crash of manual username and password --- .../src/api/routes/integrations.controller.ts | 16 +++++++ .../integrations/social/bluesky.provider.ts | 48 ++++++++++--------- .../social/social.integrations.interface.ts | 3 +- 3 files changed, 44 insertions(+), 23 deletions(-) diff --git a/apps/backend/src/api/routes/integrations.controller.ts b/apps/backend/src/api/routes/integrations.controller.ts index 918919a1..ae587603 100644 --- a/apps/backend/src/api/routes/integrations.controller.ts +++ b/apps/backend/src/api/routes/integrations.controller.ts @@ -394,6 +394,7 @@ export class IntegrationsController { } const { + error, accessToken, expiresIn, refreshToken, @@ -412,6 +413,17 @@ export class IntegrationsController { details ? JSON.parse(details) : undefined ); + if (typeof auth === 'string') { + return res({ + error: auth, + accessToken: '', + id: '', + name: '', + picture: '', + username: '', + }); + } + if (refresh && integrationProvider.reConnect) { const newAuth = await integrationProvider.reConnect( auth.id, @@ -424,6 +436,10 @@ export class IntegrationsController { return res(auth); }); + if (error) { + throw new NotEnoughScopes(error); + } + if (!id) { throw new NotEnoughScopes('Invalid API key'); } diff --git a/libraries/nestjs-libraries/src/integrations/social/bluesky.provider.ts b/libraries/nestjs-libraries/src/integrations/social/bluesky.provider.ts index bac06423..0deb4f0d 100644 --- a/libraries/nestjs-libraries/src/integrations/social/bluesky.provider.ts +++ b/libraries/nestjs-libraries/src/integrations/social/bluesky.provider.ts @@ -5,7 +5,7 @@ import { SocialProvider, } from '@gitroom/nestjs-libraries/integrations/social/social.integrations.interface'; import { makeId } from '@gitroom/nestjs-libraries/services/make.is'; -import { SocialAbstract } from '@gitroom/nestjs-libraries/integrations/social.abstract'; +import { NotEnoughScopes, SocialAbstract } from '@gitroom/nestjs-libraries/integrations/social.abstract'; import { BskyAgent, RichText } from '@atproto/api'; import dayjs from 'dayjs'; import { Integration } from '@prisma/client'; @@ -72,30 +72,34 @@ export class BlueskyProvider extends SocialAbstract implements SocialProvider { }) { const body = JSON.parse(Buffer.from(params.code, 'base64').toString()); - const agent = new BskyAgent({ - service: body.service, - }); + try { + const agent = new BskyAgent({ + service: body.service, + }); - const { - data: { accessJwt, refreshJwt, handle, did }, - } = await agent.login({ - identifier: body.identifier, - password: body.password, - }); + const { + data: { accessJwt, refreshJwt, handle, did }, + } = await agent.login({ + identifier: body.identifier, + password: body.password, + }); - const profile = await agent.getProfile({ - actor: did, - }); + const profile = await agent.getProfile({ + actor: did, + }); - return { - refreshToken: refreshJwt, - expiresIn: dayjs().add(100, 'years').unix() - dayjs().unix(), - accessToken: accessJwt, - id: did, - name: profile.data.displayName!, - picture: profile.data.avatar!, - username: profile.data.handle!, - }; + return { + refreshToken: refreshJwt, + expiresIn: dayjs().add(100, 'years').unix() - dayjs().unix(), + accessToken: accessJwt, + id: did, + name: profile.data.displayName!, + picture: profile.data.avatar!, + username: profile.data.handle!, + }; + } catch (e) { + return 'Invalid credentials'; + } } async post( diff --git a/libraries/nestjs-libraries/src/integrations/social/social.integrations.interface.ts b/libraries/nestjs-libraries/src/integrations/social/social.integrations.interface.ts index f791a026..a6d08322 100644 --- a/libraries/nestjs-libraries/src/integrations/social/social.integrations.interface.ts +++ b/libraries/nestjs-libraries/src/integrations/social/social.integrations.interface.ts @@ -13,7 +13,7 @@ export interface IAuthenticator { refresh?: string; }, clientInformation?: ClientInformation - ): Promise; + ): Promise; refreshToken(refreshToken: string): Promise; reConnect?(id: string, requiredId: string, accessToken: string): Promise; generateAuthUrl( @@ -51,6 +51,7 @@ export type GenerateAuthUrlResponse = { export type AuthTokenDetails = { id: string; name: string; + error?: string; accessToken: string; // The obtained access token refreshToken?: string; // The refresh token, if applicable expiresIn?: number; // The duration in seconds for which the access token is valid