From 33d3da2b2f8e9c941303f87e8aa38651495bd920 Mon Sep 17 00:00:00 2001 From: Elien Yang Date: Tue, 9 Jan 2024 23:20:36 -0700 Subject: [PATCH 01/10] =?UTF-8?q?fix:=20=F0=9F=90=9B=20fix=20github=20oaut?= =?UTF-8?q?h2=20issues=20after=20code=20update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit also parsed github oauth2 tokenResponse into proper json --- @core/cms/src/app.controller.ts | 3 +-- .../oauth2/github/v1/github.v1.service.ts | 12 +++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/@core/cms/src/app.controller.ts b/@core/cms/src/app.controller.ts index a16423d..6a50540 100644 --- a/@core/cms/src/app.controller.ts +++ b/@core/cms/src/app.controller.ts @@ -48,8 +48,7 @@ export class AppController { @MessagePattern("oauth") async handleOAuth(message: any) { // TODO: Add JWT and pass params - // const url = - // this.externalAuthIntegrationService.authenticate('oauth-github-v2'); + // const url = this.externalAuthIntegrationService.authenticate("oauth-github-v1"); const url = this.externalAuthIntegrationService.authenticate("oauth-google-v2"); return url; } diff --git a/@core/cms/src/external-auth-integration/auth-providers/oauth2/github/v1/github.v1.service.ts b/@core/cms/src/external-auth-integration/auth-providers/oauth2/github/v1/github.v1.service.ts index 52d33f2..9b65c4b 100644 --- a/@core/cms/src/external-auth-integration/auth-providers/oauth2/github/v1/github.v1.service.ts +++ b/@core/cms/src/external-auth-integration/auth-providers/oauth2/github/v1/github.v1.service.ts @@ -47,8 +47,14 @@ export class GithubV1OAuth2Service implements IOAuth { } const tokenResponse = await exchangeCodeForToken(this.httpService, this.config, query.code); - Logger.log("Token response", tokenResponse); - res.status(HttpStatus.OK).json(tokenResponse); + + const params = new URLSearchParams(tokenResponse); + const data = {}; + for (const [key, value] of params) { + data[key] = value; + } + + res.status(HttpStatus.OK).json(data); } catch (error) { Logger.error("Error exchanging code for token", error); throw new HttpException("Error exchanging code for token", HttpStatus.INTERNAL_SERVER_ERROR); @@ -92,7 +98,7 @@ export class GithubV1OAuth2Service implements IOAuth { userId: "aaaa", // TODO: Replace with real user ID providerInfo: { provider: "github", - version: "v2", + version: "v1", }, }; From 95d10eba1962c730b6ac7a12431db78f99157ef5 Mon Sep 17 00:00:00 2001 From: Elien Yang Date: Wed, 10 Jan 2024 12:16:18 -0700 Subject: [PATCH 02/10] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20basic=20auth?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- @core/cms/src/app.controller.ts | 14 ++++- .../external-auth-integration/@types/index.ts | 7 +++ .../auth-callback.controller.ts | 34 +++-------- .../auth-provider.factory.ts | 19 ++++-- .../auth-providers/basic-auth/@types/index.ts | 61 +++++++++++++++++++ .../basic-auth/basic-auth.module.ts | 16 +++++ .../interface/basic-auth.interface.ts | 16 +++++ .../auth-providers/oauth2/@types/index.ts | 2 + .../external-auth-integration.module.ts | 3 +- .../external-auth-integration.service.ts | 21 +++---- 10 files changed, 147 insertions(+), 46 deletions(-) create mode 100644 @core/cms/src/external-auth-integration/@types/index.ts create mode 100644 @core/cms/src/external-auth-integration/auth-providers/basic-auth/@types/index.ts create mode 100644 @core/cms/src/external-auth-integration/auth-providers/basic-auth/basic-auth.module.ts create mode 100644 @core/cms/src/external-auth-integration/auth-providers/basic-auth/interface/basic-auth.interface.ts diff --git a/@core/cms/src/app.controller.ts b/@core/cms/src/app.controller.ts index 6a50540..ad5da9a 100644 --- a/@core/cms/src/app.controller.ts +++ b/@core/cms/src/app.controller.ts @@ -15,11 +15,14 @@ export class AppController { private encryptionDecryptionService: EncryptionDecryptionService, private externalAuthIntegrationService: ExternalAuthIntegrationService, ) {} + + private readonly logger = new Logger(AppController.name); + // TODO: Add DTO @MessagePattern("create_credential") @UsePipes(new ValidateCredentialPipe()) async handleCreateCredential(message: CreateCredentialDto) { - Logger.log("Received data:", message, "AppController"); + this.logger.log(`Received data: ${message}`); return this.databaseIntegrationService.createCredential(message); } @@ -59,7 +62,7 @@ export class AppController { const token = message.token; const providerKey = message.providerKey; const data = await this.externalAuthIntegrationService.verifyToken(providerKey, token); - Logger.log(`Received data: ${JSON.stringify(data)}`, "AppController"); + this.logger.log(`Received data: ${JSON.stringify(data)}`); return data; } @@ -71,4 +74,11 @@ export class AppController { const data = await this.externalAuthIntegrationService.refreshToken(providerKey, refreshToken); return data; } + + // TODO: Add DTO + @MessagePattern("basic_auth") + async handleBasicAuth(message: any) { + // TODO: Add JWT and pass params + // return this.externalAuthIntegrationService.authenticate("oauth-google-v2"); + } } diff --git a/@core/cms/src/external-auth-integration/@types/index.ts b/@core/cms/src/external-auth-integration/@types/index.ts new file mode 100644 index 0000000..8707b92 --- /dev/null +++ b/@core/cms/src/external-auth-integration/@types/index.ts @@ -0,0 +1,7 @@ +import { OAuthString } from "../auth-providers/oauth2/@types"; +import { BasicAuthString } from "../auth-providers/basic-auth/@types"; +import { IOAuth } from "../auth-providers/oauth2/interface/ioauth.interface"; +import { IBasicAuth } from "../auth-providers/basic-auth/interface/basic-auth.interface"; + +export type AuthString = OAuthString | BasicAuthString; +export type AuthScheme = IOAuth | IBasicAuth; diff --git a/@core/cms/src/external-auth-integration/auth-callback.controller.ts b/@core/cms/src/external-auth-integration/auth-callback.controller.ts index fb95939..e30f5ec 100644 --- a/@core/cms/src/external-auth-integration/auth-callback.controller.ts +++ b/@core/cms/src/external-auth-integration/auth-callback.controller.ts @@ -1,21 +1,14 @@ -import { - Controller, - Get, - Logger, - Query, - Res, - HttpException, - HttpStatus, -} from "@nestjs/common"; +import { Controller, Get, Logger, Query, Res, HttpException, HttpStatus } from "@nestjs/common"; import { AuthProviderFactory } from "./auth-provider.factory"; import { EncryptionDecryptionService } from "~/encryption-decryption/encryption-decryption.service"; import { decodeBase64UrlToString } from "./utils"; +import { OAuthString } from "./auth-providers/oauth2/@types"; @Controller("oauth") export class AuthCallbackController { constructor( private providerFactory: AuthProviderFactory, - private encryptionDecryptionService: EncryptionDecryptionService + private encryptionDecryptionService: EncryptionDecryptionService, ) {} /** @@ -28,37 +21,26 @@ export class AuthCallbackController { async handleCallback(@Query() query: any, @Res() res: Response) { if (!query.state) { Logger.error("No state received", "AuthCallbackController"); - throw new HttpException( - "State parameter is missing", - HttpStatus.BAD_REQUEST - ); + throw new HttpException("State parameter is missing", HttpStatus.BAD_REQUEST); } try { const encryptedState = decodeBase64UrlToString(query.state); - const decryptedState = - await this.encryptionDecryptionService.decryptData(encryptedState); + const decryptedState = await this.encryptionDecryptionService.decryptData(encryptedState); const state = JSON.parse(decryptedState); - if ( - !state.providerInfo || - !state.providerInfo.provider || - !state.providerInfo.version - ) { + if (!state.providerInfo || !state.providerInfo.provider || !state.providerInfo.version) { throw new Error("Invalid state format"); } // TODO: Verify user JWT - const key = `oauth-${state.providerInfo.provider}-${state.providerInfo.version}`; + const key: OAuthString = `oauth-${state.providerInfo.provider}-${state.providerInfo.version}`; const providerService = this.providerFactory.getProvider(key); await providerService.handleCallback(query, res); } catch (error) { Logger.error(error.message, "AuthCallbackController"); - throw new HttpException( - "Error processing the OAuth callback", - HttpStatus.INTERNAL_SERVER_ERROR - ); + throw new HttpException("Error processing the OAuth callback", HttpStatus.INTERNAL_SERVER_ERROR); } } } diff --git a/@core/cms/src/external-auth-integration/auth-provider.factory.ts b/@core/cms/src/external-auth-integration/auth-provider.factory.ts index db9f483..f078575 100644 --- a/@core/cms/src/external-auth-integration/auth-provider.factory.ts +++ b/@core/cms/src/external-auth-integration/auth-provider.factory.ts @@ -1,25 +1,34 @@ import { Injectable } from "@nestjs/common"; -import { IOAuth } from "./auth-providers/oauth2/interface/ioauth.interface"; +import { AuthString, AuthScheme } from "./@types"; import { GoogleV2OAuth2Service } from "./auth-providers/oauth2/google/v2/google.v2.service"; import { GithubV1OAuth2Service } from "./auth-providers/oauth2/github/v1/github.v1.service"; +import { OAuthString } from "./auth-providers/oauth2/@types"; +import { IOAuth } from "./auth-providers/oauth2/interface/ioauth.interface"; +import { BasicAuthString } from "./auth-providers/basic-auth/@types"; +import { IBasicAuth } from "./auth-providers/basic-auth/interface/basic-auth.interface"; @Injectable() export class AuthProviderFactory { - private readonly providerMap = new Map(); + private readonly providerMap = new Map(); constructor( private googleV2OAuth2Service: GoogleV2OAuth2Service, - private githubV1OAuth2Service: GithubV1OAuth2Service + private githubV1OAuth2Service: GithubV1OAuth2Service, ) { this.registerProvider("oauth-google-v2", this.googleV2OAuth2Service); this.registerProvider("oauth-github-v1", this.githubV1OAuth2Service); } - private registerProvider(key: string, provider: IOAuth) { + private registerProvider(key: OAuthString, provider: IOAuth): void; + private registerProvider(key: BasicAuthString, provider: IBasicAuth): void; + private registerProvider(key: AuthString, provider: AuthScheme): void { this.providerMap.set(key, provider); } - public getProvider(key: string): IOAuth { + public getProvider(key: OAuthString): IOAuth; + public getProvider(key: BasicAuthString): IBasicAuth; + public getProvider(key: AuthString): AuthScheme; + public getProvider(key: AuthString): AuthScheme { const provider = this.providerMap.get(key); if (!provider) { throw new Error(`Provider not found: ${key}`); diff --git a/@core/cms/src/external-auth-integration/auth-providers/basic-auth/@types/index.ts b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/@types/index.ts new file mode 100644 index 0000000..921726c --- /dev/null +++ b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/@types/index.ts @@ -0,0 +1,61 @@ +export type BasicAuthString = `basic-${string}`; + +/** + * Represents the client credential for Basic HTTP Authentication. + * @export + * @interface ICredential + * @property {string} id - The client identifier. + * @property {string} secret - The client secret. + */ +export interface BasicAuthCredential { + username: string; + password: string; +} + +/** + * Defines the configuration for an OAuth2 provider's endpoints. + * @export + * @interface IProviderConfiguration + * @property {string} authorizeUrl - The URL for the OAuth2 authorization endpoint. + * @property {string} tokenUrl - The URL for the OAuth2 token endpoint. + * @property {string} callbackUri - The URI for the OAuth2 callback after authentication.· + * @property {string} [verifyTokenUrl] - The URL for the OAuth2 token verification endpoint. + * @property {string} refreshTokenUrl - The URL for the OAuth2 token refresh endpoint. + * @property {number} [tokenRefreshBuffer] - Time in seconds before expiration to refresh the token. + * @property {{ [key: string]: string }} [callbackUriParams] - Optional additional parameters for the callback URI. + */ +export interface BasicAuthProvider { + authenticateUrl: string; + verifyUrl?: string; +} + +/** + * Represents the full configuration for OAuth2 authentication. + * @export + * @interface IOAuth2Config + * @property {string[]} scope - The list of OAuth2 scopes requested. + * @property {ICredentials} credentials - The client credentials. + * @property {IProviderConfiguration} provider - The OAuth2 provider's endpoint configuration. + * @property {string} callbackUri - The URI for the OAuth2 callback after authentication. + * @property {{ [key: string]: string }} [callbackUriParams] - Optional additional parameters for the callback URI. + */ +export interface BasicAuthConfig { + provider: BasicAuthProvider; + credential: BasicAuthCredential; +} + +/** + * Represents the response from the OAuth2 token verification endpoint. + * @export + * @interface TokenVerificationResponse + * @property {boolean} isValid - Whether the token is valid. + * @property {number} [expiresIn] - The number of seconds until the token expires. + * @property {string[]} [scopes] - The list of scopes. + * @property {{ [key: string]: any }} [key: string] - Optional additional fields as per your application's requirements. + */ +export interface BasicAuthVerificationResponse { + isValid: boolean; + expiresIn?: number; + // Other fields as per your application's requirements + [key: string]: any; +} diff --git a/@core/cms/src/external-auth-integration/auth-providers/basic-auth/basic-auth.module.ts b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/basic-auth.module.ts new file mode 100644 index 0000000..c3be56a --- /dev/null +++ b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/basic-auth.module.ts @@ -0,0 +1,16 @@ +import { Module } from "@nestjs/common"; +import { HttpModule } from "@nestjs/axios"; +import { EncryptionDecryptionModule } from "~/encryption-decryption/encryption-decryption.module"; + +@Module({ + imports: [EncryptionDecryptionModule, HttpModule], + providers: [ + // GoogleV2OAuth2Service, + // { + // provide: "GoogleV2OAuth2Config", + // useFactory: () => new GoogleV2OAuth2Config().oAuth2Config, + // }, + ], + // exports: [GoogleV2OAuth2Service], +}) +export class BasicAuthModule {} diff --git a/@core/cms/src/external-auth-integration/auth-providers/basic-auth/interface/basic-auth.interface.ts b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/interface/basic-auth.interface.ts new file mode 100644 index 0000000..786f91f --- /dev/null +++ b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/interface/basic-auth.interface.ts @@ -0,0 +1,16 @@ +/** + * This interface represents an OAuth 2.0 provider. + */ +export interface IBasicAuth { + /** + * Returns the authentication URL for the OAuth provider. + */ + authenticate(): Promise; + + /** + * Verify the access token. + * However, the OAuth 2.0 spec (RFC 6749) doesn't clearly define the interaction between a Resource Server (RS) and Authorization Server (AS) for access token (AT) validation. + * @param accessToken The access token. + */ + verify?(): Promise; +} diff --git a/@core/cms/src/external-auth-integration/auth-providers/oauth2/@types/index.ts b/@core/cms/src/external-auth-integration/auth-providers/oauth2/@types/index.ts index 59b3248..19e8ddb 100644 --- a/@core/cms/src/external-auth-integration/auth-providers/oauth2/@types/index.ts +++ b/@core/cms/src/external-auth-integration/auth-providers/oauth2/@types/index.ts @@ -1,3 +1,5 @@ +export type OAuthString = `oauth-${string}`; + /** * Represents the client credentials for OAuth2 authentication. * @export diff --git a/@core/cms/src/external-auth-integration/external-auth-integration.module.ts b/@core/cms/src/external-auth-integration/external-auth-integration.module.ts index 6d9ae00..e48db01 100644 --- a/@core/cms/src/external-auth-integration/external-auth-integration.module.ts +++ b/@core/cms/src/external-auth-integration/external-auth-integration.module.ts @@ -3,10 +3,11 @@ import { EncryptionDecryptionModule } from "~/encryption-decryption/encryption-d import { AuthProviderFactory } from "./auth-provider.factory"; import { AuthCallbackController } from "./auth-callback.controller"; import { OAuth2Module } from "./auth-providers/oauth2/oauth2.module"; +import { BasicAuthModule } from "./auth-providers/basic-auth/basic-auth.module"; import { ExternalAuthIntegrationService } from "./external-auth-integration.service"; @Module({ - imports: [OAuth2Module, EncryptionDecryptionModule], + imports: [OAuth2Module, BasicAuthModule, EncryptionDecryptionModule], providers: [AuthProviderFactory, ExternalAuthIntegrationService], controllers: [AuthCallbackController], exports: [ExternalAuthIntegrationService], diff --git a/@core/cms/src/external-auth-integration/external-auth-integration.service.ts b/@core/cms/src/external-auth-integration/external-auth-integration.service.ts index 1114514..ca1a0c9 100644 --- a/@core/cms/src/external-auth-integration/external-auth-integration.service.ts +++ b/@core/cms/src/external-auth-integration/external-auth-integration.service.ts @@ -1,38 +1,35 @@ import { Injectable } from "@nestjs/common"; import { AuthProviderFactory } from "./auth-provider.factory"; +import { AuthString } from "./@types"; +import { OAuthString } from "./auth-providers/oauth2/@types"; +import { BasicAuthString } from "./auth-providers/basic-auth/@types"; @Injectable() export class ExternalAuthIntegrationService { constructor(private readonly authProviderFactory: AuthProviderFactory) {} - async authenticate(providerKey: string): Promise { + async authenticate(providerKey: AuthString): Promise { const authProvider = this.authProviderFactory.getProvider(providerKey); if (!authProvider) { - throw new Error( - `Authentication provider not found for key: ${providerKey}` - ); + throw new Error(`Authentication provider not found for key: ${providerKey}`); } return await authProvider.authenticate(); } - async verifyToken(providerKey: string, token: string): Promise { + async verifyToken(providerKey: OAuthString, token: string): Promise { const authProvider = this.authProviderFactory.getProvider(providerKey); if (!authProvider) { - throw new Error( - `Authentication provider not found for key: ${providerKey}` - ); + throw new Error(`Authentication provider not found for key: ${providerKey}`); } return await authProvider.verifyToken(token); } - async refreshToken(providerKey: string, refreshToken: string): Promise { + async refreshToken(providerKey: OAuthString, refreshToken: string): Promise { const authProvider = this.authProviderFactory.getProvider(providerKey); if (!authProvider) { - throw new Error( - `Authentication provider not found for key: ${providerKey}` - ); + throw new Error(`Authentication provider not found for key: ${providerKey}`); } return await authProvider.refreshToken(refreshToken); From e3f2fa012a55d57fe4af6b164c99e45f8ed75a60 Mon Sep 17 00:00:00 2001 From: Elien Yang Date: Wed, 10 Jan 2024 18:16:38 -0700 Subject: [PATCH 03/10] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20rename=20AuthSchem?= =?UTF-8?q?e=20to=20AuthService?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cms/src/external-auth-integration/@types/index.ts | 2 +- .../external-auth-integration/auth-provider.factory.ts | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/@core/cms/src/external-auth-integration/@types/index.ts b/@core/cms/src/external-auth-integration/@types/index.ts index 8707b92..698ab78 100644 --- a/@core/cms/src/external-auth-integration/@types/index.ts +++ b/@core/cms/src/external-auth-integration/@types/index.ts @@ -4,4 +4,4 @@ import { IOAuth } from "../auth-providers/oauth2/interface/ioauth.interface"; import { IBasicAuth } from "../auth-providers/basic-auth/interface/basic-auth.interface"; export type AuthString = OAuthString | BasicAuthString; -export type AuthScheme = IOAuth | IBasicAuth; +export type AuthService = IOAuth | IBasicAuth; diff --git a/@core/cms/src/external-auth-integration/auth-provider.factory.ts b/@core/cms/src/external-auth-integration/auth-provider.factory.ts index f078575..6005e4e 100644 --- a/@core/cms/src/external-auth-integration/auth-provider.factory.ts +++ b/@core/cms/src/external-auth-integration/auth-provider.factory.ts @@ -1,5 +1,5 @@ import { Injectable } from "@nestjs/common"; -import { AuthString, AuthScheme } from "./@types"; +import { AuthString, AuthService } from "./@types"; import { GoogleV2OAuth2Service } from "./auth-providers/oauth2/google/v2/google.v2.service"; import { GithubV1OAuth2Service } from "./auth-providers/oauth2/github/v1/github.v1.service"; import { OAuthString } from "./auth-providers/oauth2/@types"; @@ -9,7 +9,7 @@ import { IBasicAuth } from "./auth-providers/basic-auth/interface/basic-auth.int @Injectable() export class AuthProviderFactory { - private readonly providerMap = new Map(); + private readonly providerMap = new Map(); constructor( private googleV2OAuth2Service: GoogleV2OAuth2Service, @@ -21,14 +21,14 @@ export class AuthProviderFactory { private registerProvider(key: OAuthString, provider: IOAuth): void; private registerProvider(key: BasicAuthString, provider: IBasicAuth): void; - private registerProvider(key: AuthString, provider: AuthScheme): void { + private registerProvider(key: AuthString, provider: AuthService): void { this.providerMap.set(key, provider); } public getProvider(key: OAuthString): IOAuth; public getProvider(key: BasicAuthString): IBasicAuth; - public getProvider(key: AuthString): AuthScheme; - public getProvider(key: AuthString): AuthScheme { + public getProvider(key: AuthString): AuthService; + public getProvider(key: AuthString): AuthService { const provider = this.providerMap.get(key); if (!provider) { throw new Error(`Provider not found: ${key}`); From c31bfd5d07021b7ec7e0d258d9b18c568538afaa Mon Sep 17 00:00:00 2001 From: Elien Yang Date: Wed, 10 Jan 2024 18:25:44 -0700 Subject: [PATCH 04/10] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20Mixpanel=20b?= =?UTF-8?q?asic=20auth?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- @core/cms/src/app.controller.ts | 15 +++- .../auth-provider.factory.ts | 3 + .../basic-auth/basic-auth.module.ts | 16 ++-- .../mixpanel/v1/mixpanel.v1.config.ts | 20 +++++ .../mixpanel/v1/mixpanel.v1.service.ts | 76 +++++++++++++++++++ .../external-auth-integration.service.ts | 11 ++- 6 files changed, 131 insertions(+), 10 deletions(-) create mode 100644 @core/cms/src/external-auth-integration/auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.config.ts create mode 100644 @core/cms/src/external-auth-integration/auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.service.ts diff --git a/@core/cms/src/app.controller.ts b/@core/cms/src/app.controller.ts index ad5da9a..ecd5bf2 100644 --- a/@core/cms/src/app.controller.ts +++ b/@core/cms/src/app.controller.ts @@ -78,7 +78,18 @@ export class AppController { // TODO: Add DTO @MessagePattern("basic_auth") async handleBasicAuth(message: any) { - // TODO: Add JWT and pass params - // return this.externalAuthIntegrationService.authenticate("oauth-google-v2"); + // TODO: Add JWT + + const providerKey = message.providerKey; + return await this.externalAuthIntegrationService.authenticate(providerKey); + } + + // TODO: Add DTO + @MessagePattern("basic_auth_verify") + async handleBasicAuthVerify(message: any) { + // TODO: Add JWT + + const providerKey = message.providerKey; + return await this.externalAuthIntegrationService.verifyBasic(providerKey); } } diff --git a/@core/cms/src/external-auth-integration/auth-provider.factory.ts b/@core/cms/src/external-auth-integration/auth-provider.factory.ts index 6005e4e..15b6511 100644 --- a/@core/cms/src/external-auth-integration/auth-provider.factory.ts +++ b/@core/cms/src/external-auth-integration/auth-provider.factory.ts @@ -2,6 +2,7 @@ import { Injectable } from "@nestjs/common"; import { AuthString, AuthService } from "./@types"; import { GoogleV2OAuth2Service } from "./auth-providers/oauth2/google/v2/google.v2.service"; import { GithubV1OAuth2Service } from "./auth-providers/oauth2/github/v1/github.v1.service"; +import { MixpanelV1BasicAuthService } from "./auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.service"; import { OAuthString } from "./auth-providers/oauth2/@types"; import { IOAuth } from "./auth-providers/oauth2/interface/ioauth.interface"; import { BasicAuthString } from "./auth-providers/basic-auth/@types"; @@ -14,9 +15,11 @@ export class AuthProviderFactory { constructor( private googleV2OAuth2Service: GoogleV2OAuth2Service, private githubV1OAuth2Service: GithubV1OAuth2Service, + private mixpanelV1BasicAuthService: MixpanelV1BasicAuthService, ) { this.registerProvider("oauth-google-v2", this.googleV2OAuth2Service); this.registerProvider("oauth-github-v1", this.githubV1OAuth2Service); + this.registerProvider("basic-mixpanel-v1", this.mixpanelV1BasicAuthService); } private registerProvider(key: OAuthString, provider: IOAuth): void; diff --git a/@core/cms/src/external-auth-integration/auth-providers/basic-auth/basic-auth.module.ts b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/basic-auth.module.ts index c3be56a..8df0549 100644 --- a/@core/cms/src/external-auth-integration/auth-providers/basic-auth/basic-auth.module.ts +++ b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/basic-auth.module.ts @@ -1,16 +1,18 @@ import { Module } from "@nestjs/common"; import { HttpModule } from "@nestjs/axios"; import { EncryptionDecryptionModule } from "~/encryption-decryption/encryption-decryption.module"; +import { MixpanelV1BasicAuthService } from "./mixpanel/v1/mixpanel.v1.service"; +import { MixpanelV1BasicAuthConfig } from "./mixpanel/v1/mixpanel.v1.config"; @Module({ - imports: [EncryptionDecryptionModule, HttpModule], + imports: [HttpModule, EncryptionDecryptionModule], providers: [ - // GoogleV2OAuth2Service, - // { - // provide: "GoogleV2OAuth2Config", - // useFactory: () => new GoogleV2OAuth2Config().oAuth2Config, - // }, + MixpanelV1BasicAuthService, + { + provide: "MixpanelV1BasicAuthConfig", + useFactory: () => new MixpanelV1BasicAuthConfig().basicAuthConfig, + }, ], - // exports: [GoogleV2OAuth2Service], + exports: [MixpanelV1BasicAuthService], }) export class BasicAuthModule {} diff --git a/@core/cms/src/external-auth-integration/auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.config.ts b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.config.ts new file mode 100644 index 0000000..716149d --- /dev/null +++ b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.config.ts @@ -0,0 +1,20 @@ +import { Injectable } from "@nestjs/common"; +import { BasicAuthConfig } from "../../@types"; + +/** + * Service for configuring Mixpanel V1 Basic HTTP Authentication. + */ +@Injectable() +export class MixpanelV1BasicAuthConfig { + public basicAuthConfig: BasicAuthConfig; + + constructor() { + this.basicAuthConfig = { + provider: { + authenticateUrl: "https://mixpanel.com/api/app/me", + verifyUrl: "https://mixpanel.com/api/app/organizations/{organizationId}/service-accounts", + }, + credential: { username: process.env.MIXPANEL_V1_BASIC_USERNAME, password: process.env.MIXPANEL_V1_BASIC_PASSWORD }, + }; + } +} diff --git a/@core/cms/src/external-auth-integration/auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.service.ts b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.service.ts new file mode 100644 index 0000000..b5c40cc --- /dev/null +++ b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.service.ts @@ -0,0 +1,76 @@ +import { Injectable, Inject, Logger, Res, HttpException, HttpStatus } from "@nestjs/common"; +import { HttpService } from "@nestjs/axios"; +import { EncryptionDecryptionService } from "~/encryption-decryption/encryption-decryption.service"; +import { lastValueFrom } from "rxjs"; +import { map } from "rxjs/operators"; + +import { IBasicAuth } from "../../interface/basic-auth.interface"; +import { BasicAuthConfig, BasicAuthVerificationResponse } from "../../@types"; + +/** + * Service to handle Mixpanel V1 Basic HTTP Authentication. + */ +@Injectable() +export class MixpanelV1BasicAuthService implements IBasicAuth { + constructor( + @Inject("MixpanelV1BasicAuthConfig") private readonly config: BasicAuthConfig, + private readonly httpService: HttpService, + private readonly encryptionDecryptionService: EncryptionDecryptionService, + ) {} + + private readonly logger = new Logger(MixpanelV1BasicAuthService.name); + + /** + * Builds and returns the authentication URL for Mixpanel OAuth. + * @returns {Promise} The Mixpanel OAuth URL. + */ + async authenticate(): Promise { + try { + const { authenticateUrl } = this.config.provider; + const data = await lastValueFrom( + this.httpService.get(authenticateUrl, { auth: this.config.credential }).pipe(map((resp) => resp.data)), + ); + + return { + status: data.status, + organizationId: Object.keys(data.results?.organizations).at(0), + }; + } catch (error) { + this.logger.error(`Authentication failed: ${error}`); + const data = error.response?.data; + return data; + } + } + + /** + * Verifies the access token. + * @param _accessToken + * @returns {Promise} The response from the token verification endpoint. + */ + async verify(): Promise { + try { + const authenticationResponse = await this.authenticate(); + if (!authenticationResponse["organizationId"]) { + throw new Error("Authentication failed"); + } + + let { verifyUrl } = this.config.provider; + if (!verifyUrl) { + throw new Error("verifyUrl not found"); + } + + verifyUrl = verifyUrl.replace("{organizationId}", authenticationResponse["organizationId"]); + const data = await lastValueFrom( + this.httpService.get(verifyUrl, { auth: this.config.credential }).pipe(map((resp) => resp.data)), + ); + + return { + isValid: true, + expiresIn: data.results?.expires, + }; + } catch (error) { + this.logger.error(`Service account verification failed: ${error}`); + return { isValid: false }; + } + } +} diff --git a/@core/cms/src/external-auth-integration/external-auth-integration.service.ts b/@core/cms/src/external-auth-integration/external-auth-integration.service.ts index ca1a0c9..3853f7c 100644 --- a/@core/cms/src/external-auth-integration/external-auth-integration.service.ts +++ b/@core/cms/src/external-auth-integration/external-auth-integration.service.ts @@ -8,7 +8,7 @@ import { BasicAuthString } from "./auth-providers/basic-auth/@types"; export class ExternalAuthIntegrationService { constructor(private readonly authProviderFactory: AuthProviderFactory) {} - async authenticate(providerKey: AuthString): Promise { + async authenticate(providerKey: AuthString): Promise { const authProvider = this.authProviderFactory.getProvider(providerKey); if (!authProvider) { throw new Error(`Authentication provider not found for key: ${providerKey}`); @@ -34,4 +34,13 @@ export class ExternalAuthIntegrationService { return await authProvider.refreshToken(refreshToken); } + + async verifyBasic(providerKey: BasicAuthString): Promise { + const authProvider = this.authProviderFactory.getProvider(providerKey); + if (!authProvider) { + throw new Error(`Authentication provider not found for key: ${providerKey}`); + } + + return await authProvider.verify(); + } } From c293336f4b5b14210f58304ac143faf7a9106d70 Mon Sep 17 00:00:00 2001 From: Elien Yang Date: Wed, 10 Jan 2024 18:49:50 -0700 Subject: [PATCH 05/10] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20try=20catch?= =?UTF-8?q?=20in=20ExternalAuthIntegrationService?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth-provider.factory.ts | 2 +- .../external-auth-integration.service.ts | 20 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/@core/cms/src/external-auth-integration/auth-provider.factory.ts b/@core/cms/src/external-auth-integration/auth-provider.factory.ts index 15b6511..d62b2bc 100644 --- a/@core/cms/src/external-auth-integration/auth-provider.factory.ts +++ b/@core/cms/src/external-auth-integration/auth-provider.factory.ts @@ -34,7 +34,7 @@ export class AuthProviderFactory { public getProvider(key: AuthString): AuthService { const provider = this.providerMap.get(key); if (!provider) { - throw new Error(`Provider not found: ${key}`); + throw new Error(`Authentication provider not found for key: ${key}`); } return provider; } diff --git a/@core/cms/src/external-auth-integration/external-auth-integration.service.ts b/@core/cms/src/external-auth-integration/external-auth-integration.service.ts index 3853f7c..c014286 100644 --- a/@core/cms/src/external-auth-integration/external-auth-integration.service.ts +++ b/@core/cms/src/external-auth-integration/external-auth-integration.service.ts @@ -9,12 +9,12 @@ export class ExternalAuthIntegrationService { constructor(private readonly authProviderFactory: AuthProviderFactory) {} async authenticate(providerKey: AuthString): Promise { - const authProvider = this.authProviderFactory.getProvider(providerKey); - if (!authProvider) { - throw new Error(`Authentication provider not found for key: ${providerKey}`); + try { + const authProvider = this.authProviderFactory.getProvider(providerKey); + return await authProvider.authenticate(); + } catch (error) { + return { error: error.message }; } - - return await authProvider.authenticate(); } async verifyToken(providerKey: OAuthString, token: string): Promise { @@ -36,11 +36,11 @@ export class ExternalAuthIntegrationService { } async verifyBasic(providerKey: BasicAuthString): Promise { - const authProvider = this.authProviderFactory.getProvider(providerKey); - if (!authProvider) { - throw new Error(`Authentication provider not found for key: ${providerKey}`); + try { + const authProvider = this.authProviderFactory.getProvider(providerKey); + return await authProvider.verify(); + } catch (error) { + return { error: error.message }; } - - return await authProvider.verify(); } } From 1feaae4f8ab363382e7b3d63e1b1626bb7952901 Mon Sep 17 00:00:00 2001 From: your_username Date: Wed, 10 Jan 2024 21:36:50 -0500 Subject: [PATCH 06/10] fix: rm unused import --- .../basic-auth/mixpanel/v1/mixpanel.v1.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/@core/cms/src/external-auth-integration/auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.service.ts b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.service.ts index b5c40cc..98acc6d 100644 --- a/@core/cms/src/external-auth-integration/auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.service.ts +++ b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.service.ts @@ -1,4 +1,4 @@ -import { Injectable, Inject, Logger, Res, HttpException, HttpStatus } from "@nestjs/common"; +import { Injectable, Inject, Logger } from "@nestjs/common"; import { HttpService } from "@nestjs/axios"; import { EncryptionDecryptionService } from "~/encryption-decryption/encryption-decryption.service"; import { lastValueFrom } from "rxjs"; From 4666f07c7ac87a57b20531657e0b244888b068c4 Mon Sep 17 00:00:00 2001 From: your_username Date: Wed, 10 Jan 2024 21:49:35 -0500 Subject: [PATCH 07/10] fix: add comments of factory --- .../external-auth-integration/auth-provider.factory.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/@core/cms/src/external-auth-integration/auth-provider.factory.ts b/@core/cms/src/external-auth-integration/auth-provider.factory.ts index d62b2bc..8928f10 100644 --- a/@core/cms/src/external-auth-integration/auth-provider.factory.ts +++ b/@core/cms/src/external-auth-integration/auth-provider.factory.ts @@ -10,6 +10,7 @@ import { IBasicAuth } from "./auth-providers/basic-auth/interface/basic-auth.int @Injectable() export class AuthProviderFactory { + // A map to hold the associations between authentication keys and their corresponding services private readonly providerMap = new Map(); constructor( @@ -17,23 +18,30 @@ export class AuthProviderFactory { private githubV1OAuth2Service: GithubV1OAuth2Service, private mixpanelV1BasicAuthService: MixpanelV1BasicAuthService, ) { + // Register available authentication providers this.registerProvider("oauth-google-v2", this.googleV2OAuth2Service); this.registerProvider("oauth-github-v1", this.githubV1OAuth2Service); this.registerProvider("basic-mixpanel-v1", this.mixpanelV1BasicAuthService); } + // Function overloading for registerProvider to handle different types of auth providers private registerProvider(key: OAuthString, provider: IOAuth): void; private registerProvider(key: BasicAuthString, provider: IBasicAuth): void; private registerProvider(key: AuthString, provider: AuthService): void { + // Register a provider with a specific key in the map this.providerMap.set(key, provider); } + // Function overloading for getProvider to retrieve the appropriate type of auth provider public getProvider(key: OAuthString): IOAuth; public getProvider(key: BasicAuthString): IBasicAuth; public getProvider(key: AuthString): AuthService; + public getProvider(key: AuthString): AuthService { + // Retrieve the provider associated with the given key const provider = this.providerMap.get(key); if (!provider) { + // If the provider is not found, throw an error throw new Error(`Authentication provider not found for key: ${key}`); } return provider; From f4ac4524625c1ad44805e6d420389ee50c387b60 Mon Sep 17 00:00:00 2001 From: Elien Yang Date: Tue, 23 Jan 2024 19:49:50 -0700 Subject: [PATCH 08/10] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20add=20dtos=20for?= =?UTF-8?q?=20basic=20auth?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- @core/cms/src/app.controller.ts | 7 +++++-- @core/cms/src/dto/basic-auth-verify.dto.ts | 5 +++++ @core/cms/src/dto/basic-auth.dto.ts | 5 +++++ 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 @core/cms/src/dto/basic-auth-verify.dto.ts create mode 100644 @core/cms/src/dto/basic-auth.dto.ts diff --git a/@core/cms/src/app.controller.ts b/@core/cms/src/app.controller.ts index 491b997..98e94e7 100644 --- a/@core/cms/src/app.controller.ts +++ b/@core/cms/src/app.controller.ts @@ -8,6 +8,9 @@ import { CreateCredentialDto } from "./database-integration/dto/create-credentia import { ValidateCredentialPipe } from "./common/pipes/validate-credential.pipe"; import { ExternalAuthIntegrationService } from "./external-auth-integration/external-auth-integration.service"; +import { BasicAuthDto } from "./dto/basic-auth.dto"; +import { BasicAuthVerifyDto } from "./dto/basic-auth-verify.dto"; + @Controller() export class AppController { constructor( @@ -76,7 +79,7 @@ export class AppController { // TODO: Add DTO @MessagePattern("basic_auth") - async handleBasicAuth(message: any) { + async handleBasicAuth(message: BasicAuthDto) { // TODO: Add JWT const providerKey = message.providerKey; @@ -85,7 +88,7 @@ export class AppController { // TODO: Add DTO @MessagePattern("basic_auth_verify") - async handleBasicAuthVerify(message: any) { + async handleBasicAuthVerify(message: BasicAuthVerifyDto) { // TODO: Add JWT const providerKey = message.providerKey; diff --git a/@core/cms/src/dto/basic-auth-verify.dto.ts b/@core/cms/src/dto/basic-auth-verify.dto.ts new file mode 100644 index 0000000..828c759 --- /dev/null +++ b/@core/cms/src/dto/basic-auth-verify.dto.ts @@ -0,0 +1,5 @@ +import { BasicAuthString } from "~/external-auth-integration/auth-providers/basic-auth/@types"; + +export class BasicAuthVerifyDto { + providerKey: BasicAuthString; +} diff --git a/@core/cms/src/dto/basic-auth.dto.ts b/@core/cms/src/dto/basic-auth.dto.ts new file mode 100644 index 0000000..619950c --- /dev/null +++ b/@core/cms/src/dto/basic-auth.dto.ts @@ -0,0 +1,5 @@ +import { BasicAuthString } from "~/external-auth-integration/auth-providers/basic-auth/@types"; + +export class BasicAuthDto { + providerKey: BasicAuthString; +} From c2c8fd19e91776602d04c13e91e1497af474048e Mon Sep 17 00:00:00 2001 From: Elien Yang Date: Tue, 23 Jan 2024 19:57:31 -0700 Subject: [PATCH 09/10] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20update=20allowedCr?= =?UTF-8?q?edentials.json?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- @core/cms/src/app.controller.ts | 2 -- @core/cms/src/config/allowedCredentials.json | 17 ++++++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/@core/cms/src/app.controller.ts b/@core/cms/src/app.controller.ts index 98e94e7..5cc0fc9 100644 --- a/@core/cms/src/app.controller.ts +++ b/@core/cms/src/app.controller.ts @@ -77,7 +77,6 @@ export class AppController { return data; } - // TODO: Add DTO @MessagePattern("basic_auth") async handleBasicAuth(message: BasicAuthDto) { // TODO: Add JWT @@ -86,7 +85,6 @@ export class AppController { return await this.externalAuthIntegrationService.authenticate(providerKey); } - // TODO: Add DTO @MessagePattern("basic_auth_verify") async handleBasicAuthVerify(message: BasicAuthVerifyDto) { // TODO: Add JWT diff --git a/@core/cms/src/config/allowedCredentials.json b/@core/cms/src/config/allowedCredentials.json index ee51ae6..ca98b49 100644 --- a/@core/cms/src/config/allowedCredentials.json +++ b/@core/cms/src/config/allowedCredentials.json @@ -1,4 +1,15 @@ { - "Google": ["OAuth2", "APIKey"], - "Facebook": ["OAuth2"] -} + "Google": [ + "OAuth2", + "APIKey" + ], + "Facebook": [ + "OAuth2" + ], + "GitHub": [ + "OAuth2" + ], + "Mixpanel": [ + "Basic" + ] +} \ No newline at end of file From 79474ac74dfe95161ead38dcfa4f3528ff8bba1f Mon Sep 17 00:00:00 2001 From: Elien Yang Date: Wed, 24 Jan 2024 20:50:26 -0700 Subject: [PATCH 10/10] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20parameterize=20use?= =?UTF-8?q?r=20info=20for=20basic=20auth?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- @core/cms/src/dto/basic-auth-verify.dto.ts | 2 +- @core/cms/src/dto/basic-auth.dto.ts | 2 +- .../external-auth-integration/@types/index.ts | 4 +- .../auth-callback.controller.ts | 2 +- .../auth-provider.factory.ts | 6 +-- .../auth-providers/basic-auth/@types/index.ts | 44 ------------------- .../interface/basic-auth.interface.ts | 15 +------ .../mixpanel/v1/mixpanel.v1.config.ts | 1 - .../mixpanel/v1/mixpanel.v1.service.ts | 19 +++----- .../external-auth-integration.service.ts | 6 +-- 10 files changed, 18 insertions(+), 83 deletions(-) diff --git a/@core/cms/src/dto/basic-auth-verify.dto.ts b/@core/cms/src/dto/basic-auth-verify.dto.ts index 828c759..785bdfd 100644 --- a/@core/cms/src/dto/basic-auth-verify.dto.ts +++ b/@core/cms/src/dto/basic-auth-verify.dto.ts @@ -1,4 +1,4 @@ -import { BasicAuthString } from "~/external-auth-integration/auth-providers/basic-auth/@types"; +import { type BasicAuthString } from "~/external-auth-integration/auth-providers/basic-auth/@types"; export class BasicAuthVerifyDto { providerKey: BasicAuthString; diff --git a/@core/cms/src/dto/basic-auth.dto.ts b/@core/cms/src/dto/basic-auth.dto.ts index 619950c..8e069b6 100644 --- a/@core/cms/src/dto/basic-auth.dto.ts +++ b/@core/cms/src/dto/basic-auth.dto.ts @@ -1,4 +1,4 @@ -import { BasicAuthString } from "~/external-auth-integration/auth-providers/basic-auth/@types"; +import { type BasicAuthString } from "~/external-auth-integration/auth-providers/basic-auth/@types"; export class BasicAuthDto { providerKey: BasicAuthString; diff --git a/@core/cms/src/external-auth-integration/@types/index.ts b/@core/cms/src/external-auth-integration/@types/index.ts index 698ab78..01b8d5c 100644 --- a/@core/cms/src/external-auth-integration/@types/index.ts +++ b/@core/cms/src/external-auth-integration/@types/index.ts @@ -1,5 +1,5 @@ -import { OAuthString } from "../auth-providers/oauth2/@types"; -import { BasicAuthString } from "../auth-providers/basic-auth/@types"; +import { type OAuthString } from "../auth-providers/oauth2/@types"; +import { type BasicAuthString } from "../auth-providers/basic-auth/@types"; import { IOAuth } from "../auth-providers/oauth2/interface/ioauth.interface"; import { IBasicAuth } from "../auth-providers/basic-auth/interface/basic-auth.interface"; diff --git a/@core/cms/src/external-auth-integration/auth-callback.controller.ts b/@core/cms/src/external-auth-integration/auth-callback.controller.ts index 6f3935a..d544a16 100644 --- a/@core/cms/src/external-auth-integration/auth-callback.controller.ts +++ b/@core/cms/src/external-auth-integration/auth-callback.controller.ts @@ -2,7 +2,7 @@ import { Controller, Get, Logger, Query, Res, HttpException, HttpStatus } from " import { AuthProviderFactory } from "./auth-provider.factory"; import { EncryptionDecryptionService } from "~/encryption-decryption/encryption-decryption.service"; import { decodeBase64UrlToString } from "./utils"; -import { OAuthString } from "./auth-providers/oauth2/@types"; +import { type OAuthString } from "./auth-providers/oauth2/@types"; @Controller("oauth") export class AuthCallbackController { diff --git a/@core/cms/src/external-auth-integration/auth-provider.factory.ts b/@core/cms/src/external-auth-integration/auth-provider.factory.ts index c4f78de..0033b7d 100644 --- a/@core/cms/src/external-auth-integration/auth-provider.factory.ts +++ b/@core/cms/src/external-auth-integration/auth-provider.factory.ts @@ -1,13 +1,13 @@ import { Injectable } from "@nestjs/common"; -import { AuthString, AuthService } from "./@types"; +import type { AuthString, AuthService } from "./@types"; import { GoogleV2OAuth2Service } from "./auth-providers/oauth2/google/v2/google.v2.service"; import { GithubV1OAuth2Service } from "./auth-providers/oauth2/github/v1/github.v1.service"; import { AirtableV1OAuth2Service } from "./auth-providers/oauth2/airtable/v1/airtable.v1.service"; import { SlackV2OAuth2Service } from "./auth-providers/oauth2/slack/v2/slack.v2.service"; import { MixpanelV1BasicAuthService } from "./auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.service"; -import { OAuthString } from "./auth-providers/oauth2/@types"; +import { type OAuthString } from "./auth-providers/oauth2/@types"; import { IOAuth } from "./auth-providers/oauth2/interface/ioauth.interface"; -import { BasicAuthString } from "./auth-providers/basic-auth/@types"; +import { type BasicAuthString } from "./auth-providers/basic-auth/@types"; import { IBasicAuth } from "./auth-providers/basic-auth/interface/basic-auth.interface"; @Injectable() diff --git a/@core/cms/src/external-auth-integration/auth-providers/basic-auth/@types/index.ts b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/@types/index.ts index 921726c..c2e1447 100644 --- a/@core/cms/src/external-auth-integration/auth-providers/basic-auth/@types/index.ts +++ b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/@types/index.ts @@ -1,58 +1,14 @@ export type BasicAuthString = `basic-${string}`; -/** - * Represents the client credential for Basic HTTP Authentication. - * @export - * @interface ICredential - * @property {string} id - The client identifier. - * @property {string} secret - The client secret. - */ -export interface BasicAuthCredential { - username: string; - password: string; -} - -/** - * Defines the configuration for an OAuth2 provider's endpoints. - * @export - * @interface IProviderConfiguration - * @property {string} authorizeUrl - The URL for the OAuth2 authorization endpoint. - * @property {string} tokenUrl - The URL for the OAuth2 token endpoint. - * @property {string} callbackUri - The URI for the OAuth2 callback after authentication.· - * @property {string} [verifyTokenUrl] - The URL for the OAuth2 token verification endpoint. - * @property {string} refreshTokenUrl - The URL for the OAuth2 token refresh endpoint. - * @property {number} [tokenRefreshBuffer] - Time in seconds before expiration to refresh the token. - * @property {{ [key: string]: string }} [callbackUriParams] - Optional additional parameters for the callback URI. - */ export interface BasicAuthProvider { authenticateUrl: string; verifyUrl?: string; } -/** - * Represents the full configuration for OAuth2 authentication. - * @export - * @interface IOAuth2Config - * @property {string[]} scope - The list of OAuth2 scopes requested. - * @property {ICredentials} credentials - The client credentials. - * @property {IProviderConfiguration} provider - The OAuth2 provider's endpoint configuration. - * @property {string} callbackUri - The URI for the OAuth2 callback after authentication. - * @property {{ [key: string]: string }} [callbackUriParams] - Optional additional parameters for the callback URI. - */ export interface BasicAuthConfig { provider: BasicAuthProvider; - credential: BasicAuthCredential; } -/** - * Represents the response from the OAuth2 token verification endpoint. - * @export - * @interface TokenVerificationResponse - * @property {boolean} isValid - Whether the token is valid. - * @property {number} [expiresIn] - The number of seconds until the token expires. - * @property {string[]} [scopes] - The list of scopes. - * @property {{ [key: string]: any }} [key: string] - Optional additional fields as per your application's requirements. - */ export interface BasicAuthVerificationResponse { isValid: boolean; expiresIn?: number; diff --git a/@core/cms/src/external-auth-integration/auth-providers/basic-auth/interface/basic-auth.interface.ts b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/interface/basic-auth.interface.ts index 786f91f..7ec8f68 100644 --- a/@core/cms/src/external-auth-integration/auth-providers/basic-auth/interface/basic-auth.interface.ts +++ b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/interface/basic-auth.interface.ts @@ -1,16 +1,5 @@ -/** - * This interface represents an OAuth 2.0 provider. - */ export interface IBasicAuth { - /** - * Returns the authentication URL for the OAuth provider. - */ - authenticate(): Promise; + authenticate(username: string, password: string): Promise; - /** - * Verify the access token. - * However, the OAuth 2.0 spec (RFC 6749) doesn't clearly define the interaction between a Resource Server (RS) and Authorization Server (AS) for access token (AT) validation. - * @param accessToken The access token. - */ - verify?(): Promise; + verify?(username: string, password: string): Promise; } diff --git a/@core/cms/src/external-auth-integration/auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.config.ts b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.config.ts index 716149d..f905378 100644 --- a/@core/cms/src/external-auth-integration/auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.config.ts +++ b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.config.ts @@ -14,7 +14,6 @@ export class MixpanelV1BasicAuthConfig { authenticateUrl: "https://mixpanel.com/api/app/me", verifyUrl: "https://mixpanel.com/api/app/organizations/{organizationId}/service-accounts", }, - credential: { username: process.env.MIXPANEL_V1_BASIC_USERNAME, password: process.env.MIXPANEL_V1_BASIC_PASSWORD }, }; } } diff --git a/@core/cms/src/external-auth-integration/auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.service.ts b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.service.ts index 98acc6d..909dc28 100644 --- a/@core/cms/src/external-auth-integration/auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.service.ts +++ b/@core/cms/src/external-auth-integration/auth-providers/basic-auth/mixpanel/v1/mixpanel.v1.service.ts @@ -20,15 +20,11 @@ export class MixpanelV1BasicAuthService implements IBasicAuth { private readonly logger = new Logger(MixpanelV1BasicAuthService.name); - /** - * Builds and returns the authentication URL for Mixpanel OAuth. - * @returns {Promise} The Mixpanel OAuth URL. - */ - async authenticate(): Promise { + async authenticate(username: string, password: string): Promise { try { const { authenticateUrl } = this.config.provider; const data = await lastValueFrom( - this.httpService.get(authenticateUrl, { auth: this.config.credential }).pipe(map((resp) => resp.data)), + this.httpService.get(authenticateUrl, { auth: { username, password } }).pipe(map((resp) => resp.data)), ); return { @@ -42,14 +38,9 @@ export class MixpanelV1BasicAuthService implements IBasicAuth { } } - /** - * Verifies the access token. - * @param _accessToken - * @returns {Promise} The response from the token verification endpoint. - */ - async verify(): Promise { + async verify(username: string, password: string): Promise { try { - const authenticationResponse = await this.authenticate(); + const authenticationResponse = await this.authenticate(username, password); if (!authenticationResponse["organizationId"]) { throw new Error("Authentication failed"); } @@ -61,7 +52,7 @@ export class MixpanelV1BasicAuthService implements IBasicAuth { verifyUrl = verifyUrl.replace("{organizationId}", authenticationResponse["organizationId"]); const data = await lastValueFrom( - this.httpService.get(verifyUrl, { auth: this.config.credential }).pipe(map((resp) => resp.data)), + this.httpService.get(verifyUrl, { auth: { username, password } }).pipe(map((resp) => resp.data)), ); return { diff --git a/@core/cms/src/external-auth-integration/external-auth-integration.service.ts b/@core/cms/src/external-auth-integration/external-auth-integration.service.ts index c014286..8740fff 100644 --- a/@core/cms/src/external-auth-integration/external-auth-integration.service.ts +++ b/@core/cms/src/external-auth-integration/external-auth-integration.service.ts @@ -1,8 +1,8 @@ import { Injectable } from "@nestjs/common"; import { AuthProviderFactory } from "./auth-provider.factory"; -import { AuthString } from "./@types"; -import { OAuthString } from "./auth-providers/oauth2/@types"; -import { BasicAuthString } from "./auth-providers/basic-auth/@types"; +import type { AuthString } from "./@types"; +import type { OAuthString } from "./auth-providers/oauth2/@types"; +import type { BasicAuthString } from "./auth-providers/basic-auth/@types"; @Injectable() export class ExternalAuthIntegrationService {