From 229a8a00387463a39eefa8fe2c90957435f96fad Mon Sep 17 00:00:00 2001 From: Jan Halama Date: Mon, 29 Jan 2024 14:05:18 +0100 Subject: [PATCH] fix: verify function with request types --- src/index.ts | 2 +- src/models/index.ts | 2 +- src/models/strategyOptions.ts | 14 +++++- src/strategy.ts | 83 ++++++++++++++++++++++------------- 4 files changed, 68 insertions(+), 33 deletions(-) diff --git a/src/index.ts b/src/index.ts index 202549f..36b7355 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,7 +7,7 @@ export type { Profile, ProfileWithMetaData, StrategyOptions, - StrategyOptionWithRequest, + StrategyOptionsWithRequest, AuthenticateOptions, } from './models'; export { Strategy }; diff --git a/src/models/index.ts b/src/models/index.ts index 6e6a363..0f7ff72 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -1,6 +1,6 @@ export type { Profile, ProfileWithMetaData } from './profile'; export type { StrategyOptions, - StrategyOptionWithRequest, + StrategyOptionsWithRequest, AuthenticateOptions, } from './strategyOptions'; diff --git a/src/models/strategyOptions.ts b/src/models/strategyOptions.ts index 28b0fd2..14b74be 100644 --- a/src/models/strategyOptions.ts +++ b/src/models/strategyOptions.ts @@ -24,7 +24,7 @@ export interface StrategyOptions /** * @public */ -export interface StrategyOptionWithRequest +export interface StrategyOptionsWithRequest extends TwitterStrategyOptionsBase, Omit< PassportOAuth2StrategyOptionsWithRequest, @@ -33,6 +33,18 @@ export interface StrategyOptionWithRequest passReqToCallback: true; } +export const isStrategyOptions = ( + options: StrategyOptions | StrategyOptionsWithRequest +): options is StrategyOptions => { + return !options.passReqToCallback; +}; + +export const isStrategyOptionsWithRequest = ( + options: StrategyOptions | StrategyOptionsWithRequest +): options is StrategyOptionsWithRequest => { + return options.passReqToCallback === true; +}; + /** * @public */ diff --git a/src/strategy.ts b/src/strategy.ts index f6a3cff..8579a88 100644 --- a/src/strategy.ts +++ b/src/strategy.ts @@ -1,8 +1,17 @@ -import { Strategy as OAuth2Strategy } from 'passport-oauth2'; +import { + Strategy as OAuth2Strategy, + VerifyFunction, + VerifyFunctionWithRequest, +} from 'passport-oauth2'; import { mapUserProfile } from './mapUserProfile'; import { ProfileWithMetaData } from './models/profile'; -import { StrategyOptions } from './models/strategyOptions'; +import { + isStrategyOptions, + isStrategyOptionsWithRequest, + StrategyOptions, + StrategyOptionsWithRequest, +} from './models/strategyOptions'; import { TwitterError } from './models/twitterError'; import { TwitterUserInfoResponse } from './models/twitterUserInfo'; @@ -47,16 +56,41 @@ export class Strategy extends OAuth2Strategy { * )); * ``` */ + constructor(userOptions: StrategyOptions, verify: VerifyFunction); constructor( - options: StrategyOptions, - verify: ( - accessToken: string, - refreshToken: string, - profile: ProfileWithMetaData, - done: (error: Error | null, user?: Express.User) => void - ) => void + userOptions: StrategyOptionsWithRequest, + verify: VerifyFunctionWithRequest + ); + constructor( + userOptions: StrategyOptions | StrategyOptionsWithRequest, + verify: VerifyFunction | VerifyFunctionWithRequest + ) { + const options = Strategy.buildStrategyOptions(userOptions); + + if (isStrategyOptions(options)) { + super(options, verify as VerifyFunction); + } else if (isStrategyOptionsWithRequest(options)) { + super(options, verify as VerifyFunctionWithRequest); + } else { + throw Error('Strategy options not supported.'); + } + + this.name = 'twitter'; + this._userProfileURL = + options.userProfileURL || + 'https://api.twitter.com/2/users/me?user.fields=profile_image_url,url'; + + let scope = options.scope || []; + if (!Array.isArray(scope)) { + scope = [scope]; + } + options.scope = this.addDefaultScopes(scope, options); + } + + static buildStrategyOptions( + userOptions: StrategyOptions | StrategyOptionsWithRequest ) { - options = options || {}; + const options = userOptions || {}; options.sessionKey = options.sessionKey || 'oauth:twitter'; const authorizationURL = options.authorizationURL || 'https://twitter.com/i/oauth2/authorize'; @@ -91,25 +125,11 @@ export class Strategy extends OAuth2Strategy { options.customHeaders || {}; } - super( - { - ...options, - authorizationURL, - tokenURL, - }, - verify - ); - - this.name = 'twitter'; - this._userProfileURL = - options.userProfileURL || - 'https://api.twitter.com/2/users/me?user.fields=profile_image_url,url'; - - let scope = options.scope || []; - if (!Array.isArray(scope)) { - scope = [scope]; - } - options.scope = this.addDefaultScopes(scope, options); + return { + ...options, + authorizationURL, + tokenURL, + }; } /** @@ -189,7 +209,10 @@ export class Strategy extends OAuth2Strategy { }); } - addDefaultScopes(scopes: string[], options: StrategyOptions) { + addDefaultScopes( + scopes: string[], + options: StrategyOptions | StrategyOptionsWithRequest + ) { let skipUserProfile = false; const skipUserProfileOption = options.skipUserProfile as unknown;