Reputation: 21
The api is built with nestjs. Here is the passport strategy and the respective controller:
magic-link.strategy.ts
import MagicLoginStrategy from 'passport-magic-login';
...
@Injectable()
export class MagicLinkStrategy extends PassportStrategy(
MagicLoginStrategy,
'magiclink',
) {
constructor(
private readonly authService: AuthService,
readonly configService: ConfigService,
private readonly mailService: MailService,
) {
super({
secret: configService.get('JWT_ACCESS_SECRET'),
jwtOptions: {
expiresIn: '5m',
},
callbackUrl: 'http://localhost:4000/auth/magic-link',
sendMagicLink: async (email, magicLink) => {
await this.mailService.sendMagicLink(email, magicLink);
},
verify: async (payload, callback) =>
callback(null, this.validate(payload)),
});
}
async validate(payload: any) {
const user = await this.authService.validateUserByEmail(
payload.destination,
);
if (!user) {
console.log('User not found');
throw new UnauthorizedGraphQLApiError();
}
return user;
}
}
AuthController.ts
@Controller('auth')
export class AuthController {
constructor(
private authService: AuthService,
private magicLinkStrategy: MagicLinkStrategy,
) {}
@Public()
@Get('magic-link')
@UseGuards(AuthGuard('magiclink'))
async magicLinkCallback(@Req() req) {
// // The user has been authenticated successfully
// // You can now create a JWT for the user and send it to the client
const user = req.user;
const tokens = this.authService.generateTokens(user);
const { accessToken, refreshToken } = tokens;
this.authService.setRefreshTokenCookie(req.res, refreshToken);
// req.res.redirect('http://localhost:3000/');
return {
accessToken,
user,
};
}
@Public()
@Post('request-magic-link')
requestMagicLink(@Req() req, @Res() res) {
return this.magicLinkStrategy.send(req, res);
}
}
The magic link in the email sends the user to "/auth/magic-link" in the AuthController (see above), where the link gets validated and, if successful ,returns the access token:
return {
accessToken,
user,
};
Since the client is a react spa, (running under localhost:3000), i ´m not sure how to login the user clientside with the returned accessToken..
Here is the flow for a login with email and password:
User enters email and password in the react form, sends it to the api via apollo client
Api valdates credentials and creates an access token and a refresh token which are returned to the client
Client puts access token into local storage and set the state in a react context to "loggedIn"
User is allowed to enter proteced pages
Step 3 won´t work with the passwordless approach i´ve outlined before. How do i do this?
Upvotes: 0
Views: 69