passport: Extending `PassportStrategy` does not take provider specific OAuth2 options in account
I’m submitting a…
[ ] Regression
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.
Current behavior
Extending PassportStrategy does not work as expected. In case of extending PassportStrategy(Strategy, 'google') additional OAuth2 options, respectively provider specific options like e.g. approval_prompt passed to Superconstructor are NOT applied. So it is not possible to obtain a REFRESH_TOKEN.
Expected behavior
Additional, provider specific OAuth2 options can be passed through the Superconstructor and become effective.
Minimal reproduction of the problem with instructions
My Google OAuth2 strategy implementation:
import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy } from 'passport-google-oauth20';
import { AuthService, Provider } from './auth.service';
import { ConfigService } from '../config/config.service';
import { User } from '../api/user/user.interface';
@Injectable()
export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
constructor(configService: ConfigService, private readonly authService: AuthService) {
super({
clientID: configService.get('OAUTH_CLIENT_ID'),
clientSecret: configService.get('OAUTH_CLIENT_SECRET'),
callbackURL: `${configService.baseUrl}/auth/google/callback`,
passReqToCallback: true,
scope: ['email', 'profile'],
// NOT WORKING
approval_prompt: 'force',
access_type: 'offline',
});
}
async validate(request: any, accessToken: string, refreshToken: string, profile: any, done: (err: any, result: any) => void) {
// ...
}
// WORKAROUND: pass options to superclass auth call by overriding superclass method
authorizationParams(options: any): any {
return Object.assign(options, {
approval_prompt: 'force',
access_type: 'offline',
});
}
}
Environment
@nestjs/passport: 6.0.0
For Tooling issues:
- Node version: 10.11.0
- Platform: Mac
About this issue
- Original URL
- State: open
- Created 5 years ago
- Reactions: 12
- Comments: 31 (12 by maintainers)
While that does work it skips the validation and sanitization the original function does. You’re able to achieve the same by overriding the authenticate function and it retains all original behavior of the strategy.
Edit: You can achieve similar results by calling super.authorizationParams, however if anyone stumbled upon custom_params or custom parameters this would be the way it’d work across providers (potentially).
https://github.com/nestjs/passport/blob/master/lib/auth.guard.ts#L82
We pass
AuthModuleOptionsto theauthenticate()function, so you should be able to put them here:@iveselin just try with:
The problem is, that non-standard params passed through constructor
super()call are ignored, which normally should work (https://github.com/jaredhanson/passport-google-oauth2/blob/master/lib/strategy.js#L159). Just useauthorizationParamsas in the example above.According to Facebook docs for api 2.4 (current is 3.2)
https://developers.facebook.com/blog/post/2015/07/08/graph-api-v2.4/
This means even if I use
profileFieldsin Strategy constructorI still have to pass additional params to
authorizefunction like thisThanks to @csidell-earny his workaround works fine for me
Here ya go https://github.com/johnbiundo/nestpasspr94
@csidell-earny I tried your PR with my app. Identical code with only swapping in/out your version of
@nestjs/passportworks with current version, fails as follows.I can’t make this repo public, but if it matters, I could see if I can strip it down. But it looks like it has to do with the fact that I’m also using Passport sessions, a la stuff like this in my main.ts:
I am not sure why we need a separate method just as @kamilmysliwiec said. The above suggestion makes perfect sense to me.
I have Google, Twitter & Facebook working altogether with separate Strategy & Guards. An authenticate method with
customParametersseems un-necessary to me as well. All I am doing is passing different options to constructor of the new strategies.Also, just to be clear, according to
passport-google-oauth2’s strategy.js,CC: @johnbiundo