ArcadeHero
ArcadeHero

Reputation: 21

Trouble implementing a a passwordless login with a react spa as client

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:

Step 3 won´t work with the passwordless approach i´ve outlined before. How do i do this?

Upvotes: 0

Views: 69

Answers (0)

Related Questions