Konstantin
Konstantin

Reputation: 21

Get Auth0 user info in NestJS

I am trying to do Auth0 authorization in NestJS, but i am not sure how to get user's data on callback url handler.

At normal express function this could be solved by code below. I call passport.authenticate('auth0', function (err, user, info) { }) function with callback function and receive user date in it.

// Perform the final stage of authentication and redirect to previously requested URL or '/user'
router.get('/callback', function (req, res, next) {
  passport.authenticate('auth0', function (err, user, info) {
    if (err) { return next(err); }
    if (!user) { return res.redirect('/login'); }
    req.logIn(user, function (err) {
      if (err) { return next(err); }
      const returnTo = req.session.returnTo;
      delete req.session.returnTo;
      res.redirect(returnTo || '/user');
    });
  })(req, res, next);
});

But i am not sure how this should be done in NestJS style. With decorators and guards. In NestJS i add next function. But how should i get user's data in it?

  @Get('cb')
  async callback(): Promise<any> {
    // WHAT SHOULD I CALL HERE?
  }

auth.controller.ts

@Controller('auth')
export class AuthController {
  constructor(
    private readonly authService: AuthService,
  ) {}

  @Get('login')
  @UseGuards(AuthGuard('auth0'))
  async login(): Promise<any> {
    const v = this.configService.get('TEST');
    return { r: 'ok1', v };
  }

  @Get('cb')
  // @UseGuards(AuthGuard('auth0'))
  async callback(): Promise<any> {
    // WHAT SHOULD I CALL HERE?
  }

}

auth0.strategy.ts

@Injectable()
export class Auth0Strategy extends PassportStrategy(Strategy) {
  constructor(
    private readonly authService: AuthService,
    private readonly configService: ConfigService,
  ) {
    super({
      domain: 'zzzz',
      clientID: 'zzzz',
      clientSecret: 'zzzz',
      callbackURL: '/auth/cb',
    });
  }

  async validate(payload) {
    console.log('Auth0Strategy payload', payload);
    return payload;
  }
}

Upvotes: 2

Views: 3139

Answers (1)

Ivan Vasiljevic
Ivan Vasiljevic

Reputation: 5718

It seems that there is example on github how you can use Nest.js with Auth0.

If you check given example you can find that you need to do next things:

Define empty callback endpoint in AuthController:

@Get('/callback')
public callback() {}

Define middleware

@Injectable()
class Auth0CallbackMiddleware implements NestMiddleware {
  resolve() {
    return authenticate('auth0', {
      successRedirect: '/user',
      failureRedirect: '/'
    }, (req, res) => {
        if (!req.user) {
            throw new Error('user null');
        }
        res.redirect("/");
    }
    );
  }
}

Use that middleware:

@Module({
  providers: [Auth0Strategy, Auth0LoginMiddleware, Auth0CallbackMiddleware],
  controllers: [AppController]
})
export class ApplicationModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer


.apply(Auth0LoginMiddleware)
  .forRoutes({path: '/login', method: RequestMethod.ALL})

  .apply(Auth0CallbackMiddleware)
  .forRoutes({path: '/callback', method: RequestMethod.ALL})

  .apply(EnsureLoggedIn)
  .forRoutes({path: '/user', method: RequestMethod.ALL});

  }
}

Check your validate function inside Auth0Strategy. In example it looks little bit different:

async (accessToken, refreshToken, extraParams, profile, done) => {
        return done(null, profile);
}

Upvotes: 1

Related Questions