Open carneles opened 6 years ago
Hi @carneles
If we have a look at the nbStrategiesFactory
function, responsible for creating the strategies you declare, we see :
export function nbStrategiesFactory(options: NbAuthOptions, injector: Injector): NbAuthStrategy[] {
const strategies = [];
options.strategies
.forEach(([strategyClass, strategyOptions]: [NbAuthStrategyClass, NbAuthStrategyOptions]) => {
const strategy: NbAuthStrategy = injector.get(strategyClass);
strategy.setOptions(strategyOptions);
strategies.push(strategy);
});
return strategies;
}
If you declare two different strategies with the same class (i.e. two NbPasswordAuthStrategy
in your case), then for the second(yyy), the injector.get(strategyClass)
points to the first (xxx). The next line (setOptions()
) overwrites all the properties of 'xxx' including name.
=> So you can use only yyy
.
@nnixaa it seems that we cannot for now declare two strategies with the same class. Would it be interesting to do something for troubleshoot that?
Hey @carneles, thanks for reporting and @alain-charles, thanks for digging in. Yes, it looks like we cannot have two strategies with the same class and this is very unfortunate.
As for a workaround, you can create a second strategy class, extend it from the NbPasswordStrategy
and provide it:
@Injectable()
export class NbSecondPasswordStratey extends NbPasswordStrategy {}
...
providers: [
...
NbSecondPasswordStratey,
]
Then you can declare both strategies.
But having two strategies with the same class under different names was our original intention, looks like we missed it.
Could you please explain it little more?
I created another class and extended the Auth strategy as follow:
import {Injectable} from '@angular/core';
import {NbOAuth2AuthStrategy} from '@nebular/auth';
@Injectable()
export class Nb0Auth2AuthFacebookStrategy extends NbOAuth2AuthStrategy {
}
I added in the Core Modules:
export const NB_CORE_PROVIDERS = [
...DataModule.forRoot().providers,
...NbAuthModule.forRoot({
strategies: [
NbPasswordAuthStrategy.setup({
name: 'email',
baseEndpoint: config.API_URL + 'auth/',
login: {
endpoint: 'sign-in',
},
register: {
endpoint: 'sign-up',
},
logout: {
endpoint: 'sign-out',
},
requestPass: {
endpoint: 'password-request',
},
resetPass: {
endpoint: 'password-reset',
},
token: {
class: NbAuthJWTToken,
key: 'token',
},
}),
Nb0Auth2AuthFacebookStrategy.setup({
name: 'facebook',
clientId: '249362002407540',
authorize: {
endpoint: 'https://www.facebook.com/v3.2/dialog/oauth',
responseType: NbOAuth2ResponseType.TOKEN,
scope: 'basic_info',
redirectUri: 'http://localhost:4200/auth/callback-facebook',
},
}),
],
forms: {
login: {
socialLinks: socialLinks,
},
register: {
socialLinks: socialLinks,
},
},
}).providers,
Where do I need to add it as provider? In the login? And Do I need to leave the class empty?
@maihannijat yes, you can leave the class empty sinse you just need a new service. As for the provider - you can put it into the NB_CORE_PROVIDERS
list.
@nnixaa the above should work fine according to your explanation, but it does not. It still has the same behavior.
Error during template compile of 'AppModule' Function calls are not supported in decorators but 'Nb0Auth2AuthFacebookStrategy' was called in 'CoreModule' 'CoreModule' references 'NB_CORE_PROVIDERS' 'NB_CORE_PROVIDERS' calls 'Nb0Auth2AuthFacebookStrategy'.
Hey @nnixaa could you solve it? I have the same problem when trying to do it with more than one NbOAuth2AuthStrategy.
@Injectable()
export class NbGoogleOAuth2Strategy extends NbOAuth2AuthStrategy {}
@Injectable()
export class NbFacebookOAuth2Strategy extends NbOAuth2AuthStrategy {}
export const NB_CORE_PROVIDERS = [
...NbAuthModule.forRoot({
strategies: [
NbDummyAuthStrategy.setup({
name: 'email',
delay: 3000,
}),
NbOAuth2AuthStrategy.setup({
name: 'google',
clientId: '*******JoYA',
clientSecret: '',
authorize: {
endpoint: 'https://accounts.google.com/o/oauth2/v2/auth',
responseType: NbOAuth2ResponseType.TOKEN,
scope: 'https://www.googleapis.com/auth/userinfo.profile',
redirectUri: 'http://localhost:4100/example/oauth2/callback',
}
}),
NbFacebookOAuth2Strategy.setup({
name: 'facebook',
clientId: '****3259',
clientSecret: '***aea2f6',
authorize:{
endpoint: 'https://www.facebook.com/v3.2/dialog/oauth',
responseType: NbOAuth2ResponseType.TOKEN,
redirectUri: 'http://localhost:4200/callback',
}
}),
],
forms: {
login: {
socialLinks: socialLinks,
},
register: {
socialLinks: socialLinks,
},
},
}).providers
];
Error:
Following screenshots are from the debug which comes from the file: auth.service.js > this.strategies...
export const NB_CORE_PROVIDERS = [
...NbAuthModule.forRoot({
// ...
}).providers,
NbGoogleOAuth2Strategy,
NbFacebookOAuth2Strategy,
];
Adding strategies as services should do the trick. Haven't been able to test the code though, let me know how it goes.
Have tried didn't help
export const NB_CORE_PROVIDERS = [ ...NbAuthModule.forRoot({ // ... }).providers, NbGoogleOAuth2Strategy, NbFacebookOAuth2Strategy, ];
Adding strategies as services should do the trick. Haven't been able to test the code though, let me know how it goes.
Hey @nnixaa , we have tried and it didn't work, apreciate help. Any other ways???
Right, one more step and it should be fine as a workaround:
@Injectable()
export class NbGoogleOAuth2Strategy extends NbOAuth2AuthStrategy {
static setup(options: NbOAuth2AuthStrategyOptions): [NbAuthStrategyClass, NbOAuth2AuthStrategyOptions] {
return [NbGoogleOAuth2Strategy, options]; // HERE we make sure our strategy reutrn correct class reference
}
}
@Injectable()
export class NbFacebookOAuth2Strategy extends NbOAuth2AuthStrategy {
static setup(options: NbOAuth2AuthStrategyOptions): [NbAuthStrategyClass, NbOAuth2AuthStrategyOptions] {
return [NbFacebookOAuth2Strategy, options]; // HERE we make sure our strategy reutrn correct class reference
}
}
Yes, it works correctly @nnixaa Thanks!
Good evening, and how can I send the user data login google to show your photo and name in the headers?
Was it fixed in version 4.4 or higher?
any update on the fix or documentation update?
Still not possible to create multiple strategies
@nnixaa I did not get it, guys. Where exactly should I add each portion of code?
Please update the documentation. Reading the comments on this issue is not straightforward. I am not sure where to put this code and how to make this work.
I find that replacing the static setup in my extended implementation in order to return an array of my custom class and options works well for me.
@Injectable()
export class NbCustomAuthStrat extends NbPasswordAuthStrategy {
protected http: HttpClient;
static setup(options): [NbAuthStrategyClass, NbPasswordAuthStrategyOptions] {
return [NbCustomAuthStrat, options];
}
}
I implemented more than one strategy like this:
But when trying to use xxx strategy, it always returns "There is no Auth Strategy registered under 'xxx' name" error:
Was trying to debug by adding log build result of auth.service.js:
But in the result the strategies does not have 'name' field: