Reputation: 117
I'm trying to set up the Facebook authentication strategy on my app using Passport.js, Express and TypeScript. I could understand the dataflow of the process thanks to this article from Hacker Noon.
But when it comes to the verification callback function, things get a little troublesome. I need to check whether the user is already logged in, thus the access to the Request object is necessary. I've checked in the passport-facebook
module docs that passReqToCallback: true
can be set on the strategy options to enable this.
However when I pass the req
parameter to the callback function, the compiler throws the following error:
Argument of type '(req: Request, accessToken: string, _refreshToken: string, profile: Profile, done: any) => void' is not assignable to parameter of type 'VerifyFunction'.
Looking around the type definitions of the Passport.js module I found this:
export type VerifyFunction =
(accessToken: string, refreshToken: string, profile: Profile, done: (error: any, user?: any, info?: any) => void) => void;
export type VerifyFunctionWithRequest =
(req: express.Request, accessToken: string, refreshToken: string, profile: Profile, done: (error: any, user?: any, info?: any) => void) => void;
export class Strategy implements passport.Strategy {
constructor(options: StrategyOptionWithRequest, verify: VerifyFunctionWithRequest);
constructor(options: StrategyOption, verify: VerifyFunction);
name: string;
authenticate(req: express.Request, options?: object): void;
}
So, in theory, the declaration
new Strategy(fbConfig, (req: Request, accessToken: string, _refreshToken: string, profile: Profile, done: any) => { ... });
should be accepted with no problems.
Here is the full fbConfig
declaration:
const fbConfig = {
clientID: "",
clientSecret: "",
callbackURL: "",
passReqToCallback: true,
profileFields: [
"id",
"name",
"birhday",
"gender",
"email",
"location",
"hometown"
]
};
And my tsconfig.json
:
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"strict": true,
"noImplicitAny": true,
"esModuleInterop": true,
"baseUrl": ".",
"outDir": "dist",
"paths": {
"@models/*": ["./src/models/*"],
"@configs/*": ["./src/configs/*"],
"@controllers/*": ["./src/controllers/*"]
}
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
If anyone could help me out with this, I'd appreciate it pretty much!
Upvotes: 0
Views: 2346
Reputation: 117
I've tried what Shanon Jackson recommended, but it didn't work. The compiler couldn't recognize the overloaded constructor for the Strategy
class.
So what I did was:
new Strategy(
fbConfig as StrategyOptionWithRequest,
(
req: Request,
accessToken: string,
_refreshToken: string,
profile: Profile,
done
) => { ... }
);
I suppose that casting the fbConfig
object to StrategyOptionWithRequest
forced the compiler to use the constructor that expected that interface. Then I annotated the types of the callback function parameters, but left done
to the compiler inference system to deal with. Annotating it to any
seemed to mess a bit with VSCode's IntelliSense system, making it do not display done
's expected parameters.
Upvotes: 1
Reputation: 6531
Typescript actually has a NodeJS starter kit with Facebook OAuth completely setup so people can observe how it's implemented here:
https://github.com/microsoft/TypeScript-Node-Starter And you can find their passport implemented with Facebook here: https://github.com/microsoft/TypeScript-Node-Starter/blob/master/src/config/passport.ts
It Looks like they are casting "Request" to any
i suspect it's because of conflicting definitions of Request
between express/passport/Typescript standard library but can't know for sure
Upvotes: 0