Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Azure AD authentication #53

Closed
mavortius opened this issue Mar 26, 2019 · 5 comments
Closed

Support for Azure AD authentication #53

mavortius opened this issue Mar 26, 2019 · 5 comments

Comments

@mavortius
Copy link

I'm submitting a...


[ ] Regression 
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

Expected behavior

Validate jwt token using Azure AD.

Minimal reproduction of the problem with instructions

What is the motivation / use case for changing the behavior?

Environment


Nest version: X.Y.Z

 
For Tooling issues:
- Node version: XX  
- Platform:  

Others:

@kamilmysliwiec
Copy link
Member

https://github.com/AzureAD/passport-azure-ad

@aramalipoor
Copy link

aramalipoor commented Jun 21, 2020

@kamilmysliwiec looks like because of this block and they way NestJS Passport wrapper works passport-azure-ad cannot populate proper arguments to the "verify" (aka "validate") method. Because "arity" or number of verify function arguments will be calculated as 0 :( in here: https://github.com/AzureAD/passport-azure-ad/blob/96c7a193737f03a270b4eb0d99ce2d59256da9a9/lib/oidcstrategy.js#L109

import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { OIDCStrategy } from 'passport-azure-ad';

import { configService } from '../config/config.service';
import { ProfileProvider } from '../user/user.types';
import { AuthService } from './auth.service';

@Injectable()
export class AzureAdStrategy extends PassportStrategy(
  OIDCStrategy,
  'azure-ad',
) {
  constructor(private readonly authService: AuthService) {
    super(configService.getAzureAdConfig());
  }

  async validate(iss, sub, profile, accessToken, refreshToken, done: Function) {
    try {
      const jwt: string = await this.authService.handleOAuthLogin(
        accessToken,
        refreshToken,
        profile.id,
        ProfileProvider.AZURE_AD,
      );

      done(null, {
        jwt,
      });
    } catch (err) {
      console.log('Azure AD Strategy failure', err);
      done(err, false);
    }
  }
}

Using above class first argument is either request (if passReqToCallback: true) or profile object and last argument is "done" function.

Not "profile" nor "request" contain the accessToken or refreshToken 🤔

Is it possible to work-around this somehow? Like directly registering Azure-AD with passport as a quick fix for now?

@LyricL-Gitster
Copy link

LyricL-Gitster commented Jun 30, 2020

@aramalipoor In case you're still stuck around this, I'm following a solution where you can hack a custom callback function based on this issue:
https://github.com/AzureAD/passport-azure-ad/issues/424#issue-447820817

@aramalipoor
Copy link

Thanks @llhupp, I ended up directly providing the callback function instead of using NestJs strategy:

import passport from 'passport';
import { Injectable, OnModuleInit } from '@nestjs/common';
import { OIDCStrategy } from 'passport-azure-ad';

import { configService } from '../config/config.service';
import { ProfileProvider } from '../user/user.types';
import { AuthService } from './auth.service';

@Injectable()
export class AzureadStrategy extends OIDCStrategy implements OnModuleInit {
  onModuleInit() {
    passport.use('azuread', this);
  }

  constructor(private readonly authService: AuthService) {
    super(
      configService.getAzureadConfig(),
      (iss, sub, profile, accessToken, refreshToken, done) => {
        try {
          return this.authService
            .handleOAuthLogin(
              accessToken,
              refreshToken,
              profile.oid,
              ProfileProvider.AZUREAD,
            )
            .then(jwt => {
              done(null, {
                jwt,
              });
            })
            .catch(err => {
              console.log('Azure AD Strategy failure 1', err);
              done(err, false);
            });
        } catch (err) {
          console.log('Azure AD Strategy failure 2', err);
          done(err, false);
          return err;
        }
      },
    );
  }
}

@0x0ece
Copy link

0x0ece commented May 17, 2021

FYI, I made a proposal to passport-azure-ad to explicitly set the verify callback signature.

With that PR, setting verifyArity: 8 in the options lets you retrieve the tokens.

@Injectable()
export class AzureAdStrategy extends PassportStrategy(OIDCStrategy) {
  constructor (private readonly moduleRef: ModuleRef) {
    super({
      ...
      passReqToCallback: true,
      verifyArity: 8,
    })
  }

  async validate (
    request, iss, sub, profile, jwtClaims, access_token, refresh_token, params
  ): Promise<RequestUser | null> {
     ...
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants