Closed dilame closed 5 years ago
One more thing. I created custom guard as described in https://docs.nestjs.com/techniques/authentication
And even include it in providers
section of module, no console logs.
@Injectable()
export class GoogleAuthGuard extends AuthGuard('google'){
canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> {
console.log('Custom google guard');
}
handleRequest(err, user, info) {
console.log('Custom google guard');
}
}
Just wanted to give a heads up, the default option for sessions is false, so this may be why you are not getting sessions to create for you.
https://github.com/nestjs/passport/blob/master/lib/options.ts
May need to add PassportModule.register({ session: true })
in the module import
Also, your GoogleAuthGuard needs to follow the canActivate
signature
@Injectable()
export class GoogleAuthGuard extends AuthGuard('google') {
canActivate(context: ExecutionContext) {
const request = context.switchToHttp().getRequest();
super.logIn(request);
return super.canActivate(context);
}
}
But my GoogleAuthGuard
follows this signature, you can see it in my last message, the problem that it is not called.
It seems like i did the things right, after 3 days of googling and reading nest sources. Now i can say that Nest docs needs a huge improvements in Authentication
section 😄
Let's track this issue here https://github.com/nestjs/docs.nestjs.com/issues/99
但我
GoogleAuthGuard
遵循这个签名,你可以在我的上一条消息中看到它,它没有被调用的问题。 经过3天的谷歌搜索和阅读巢源,似乎我做的事情是正确的。现在我可以说Nest文档需要对Authentication
部分进行大幅改进😄
解决了吗?我也遇到了这个问题。
Here is how i got passport with a local strategy and sessions to work.
// main.ts
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// add 'express-session' (npm install express-session)
app.use(session({
secret: 'hello-world',
}));
app.use(cookieParser());
// init 'passport' (npm install passport)
app.use(passport.initialize());
app.use(passport.session());
await app.listen(3000);
}
// app.module.ts
@Module({
imports: [
// configure default options for passport
PassportModule.register({
defaultStrategy: 'local',
session: true,
}),
],
controllers: [
UserController,
],
providers: [
AuthService,
// add our providers
LocalStrategy, // simply by importing them will register them to passport (under the hood it calls `passport.use(...)`)
LocalSerializer,
LocalAuthGuard,
],
})
export class AppModule {}
import { Strategy } from 'passport-local';
@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
constructor(
private readonly authService: AuthService,
) {
super();
}
async validate(email: string, password: string, done: CallableFunction) {
// add your custom login check here. and return the User object.
return await this.authService.signIn(email, password)
.then(user => {
done(null, user);
})
.catch(error => done(error));
}
}
Create logic on how our user
object should be serialized / deserialized. Under the hood, this will setup the passport.serializeUser(...)
and passport.deserializeUser(...)
@Injectable()
export class LocalSerializer extends PassportSerializer {
constructor(
private readonly authService: AuthService,
private readonly userRepository: UserRepository,
) {
super();
}
serializeUser(user: User, done: CallableFunction) {
done(null, user.id);
}
async deserializeUser(userId: string, done: CallableFunction) {
return await this.userRepository.findOneOrFail({ id: Number(userId) })
.then(user => done(null, user))
.catch(error => done(error));
}
}
By default the AuthGuard
does not call req.logIn(...)
to fix this we extend the AuthGuard
and simply call it ourself if successfully logged in. (this will trigger the session storage)
@Injectable()
export class LocalAuthGuard extends AuthGuard('local') {
async canActivate(context: ExecutionContext): Promise<boolean> {
const can = await super.canActivate(context);
if (can) {
const request = context.switchToHttp().getRequest();
super.logIn(request);
}
return true;
}
}
// user.controller.ts
export class UserController {
@Get('/signin')
@UseGuards(new LocalAuthGuard()) // notice we use our customized AuthGuard
signIn(@Query() signInDTO: UserSignInDTO) {
return {
message: 'You are now signed in',
};
}
}
@madsleejensen nice example, thank you. I have one fix for your code - we shoud
await super.logIn(request);
Because if you do some async stuff in serializeUser
- the session won't establish
For those following/landing on this thread, there are a couple of recent documents that should help 1) The authentication chapter was completely re-written (as of July 2019) with an end-to-end example 2) A recent (July 2019) article on dev.to on sessions covers sessions and was reviewed by the Nest core team.
Still no examples with session in docs 😄 But second article looks pretty useful, thank you!
Guys here is what you are looking for - boilerplate with local/google auth, sessions, and ACL https://github.com/TrejGun/nest-authorization
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
I'm submitting a...
Current behavior
I don't understand how to implement passport sessions with session storage in nest. I read all the documentation three times and searched all the Google - no info. But it's the most common task. Basically all i need is save current user in session using
req.logIn()
and then check it withreq.isAuthenticated()
in, maybe, guard.Now i have simple google stategy
By the way, shoud i add
implements AbstractStrategy
to this? Without it WebStorm saysBut there is nothing in docs about AbstractStrategy.
And auth.controller.ts
How am i supposed to save authentication in session with
req.logIn()
?P.S. i will try to imrove docs if we will find the answers