如何将自定义值传递给 Azure AD B2C 并需要 return 该参数以及响应或通用重定向 URI?

How can I pass a custom value to Azure AD B2C and need to return that parameter along with the response or with the common Redirect URI?

我必须处理多个登录 pages/applications 需要重定向到一个公共登录页面 index.html 并且需要访问自定义字符串来识别请求应用。令牌生成端点对所有登录页面都是通用的。

场景:

我已经尝试使用 'state' 和 'extraQueryParameters',但不确定它们如何按照我的要求工作。

const loginRequest = {
        scopes: ["openid", "profile"],
        extraQueryParameters: { campaignId: 'hawaii', ui_locales: 'es' }
      };

如有任何帮助,我们将不胜感激。提前致谢。

-- app-config.ts

    import { Configuration } from 'msal';
    import { MsalAngularConfiguration } from '@azure/msal-angular';
    
    // this checks if the app is running on IE
    export const isIE = window.navigator.userAgent.indexOf('MSIE ') > -1 || window.navigator.userAgent.indexOf('Trident/') > -1;
    
    export const b2cPolicies = {
        names: {
            signUpSignIn: "b2c_1_susi",
            resetPassword: "b2c_1_reset",
        },
        authorities: {
            signUpSignIn: {
                authority: "https://fabrikamb2c.b2clogin.com/fabrikamb2c.onmicrosoft.com/b2c_1_susi"
            },
            resetPassword: {
                authority: "https://fabrikamb2c.b2clogin.com/fabrikamb2c.onmicrosoft.com/b2c_1_reset"
            } 
        }
    }
    
    export const apiConfig: {b2cScopes: string[], webApi: string} = {
        b2cScopes: ['https://fabrikamb2c.onmicrosoft.com/helloapi/demo.read'],
        webApi: 'https://fabrikamb2chello.azurewebsites.net/hello'
    };
    
    export const msalConfig: Configuration = {
        auth: {
            clientId: "e760cab2-b9a1-4c0d-86fb-ff7084abd902",
            authority: b2cPolicies.authorities.signUpSignIn.authority,
            redirectUri: "http://localhost:6420/",
            postLogoutRedirectUri: "http://localhost:6420/",
            navigateToLoginRequestUrl: true,
            validateAuthority: false,
          },
        cache: {
            cacheLocation: "localStorage",
            storeAuthStateInCookie: isIE, // Set this to "true" to save cache in cookies to address trusted zones limitations in IE
        },
    }
    
    export const loginRequest = {
        scopes: ['openid', 'profile'],
 extraQueryParameters: { userPage: 'Page1', ui_locales: 'es' }
    };
    
    // Scopes you enter will be used for the access token request for your web API
    export const tokenRequest: {scopes: string[]} = {
        scopes: apiConfig.b2cScopes // i.e. [https://fabrikamb2c.onmicrosoft.com/helloapi/demo.read]
    };
    
    export const protectedResourceMap: [string, string[]][] = [
        [apiConfig.webApi, apiConfig.b2cScopes] // i.e. [https://fabrikamb2chello.azurewebsites.net/hello, ['https://fabrikamb2c.onmicrosoft.com/helloapi/demo.read']]
    ];
    
    export const msalAngularConfig: MsalAngularConfiguration = {
        popUp: !isIE,
        consentScopes: [
            ...loginRequest.scopes,
            ...tokenRequest.scopes,
 

   ],
    unprotectedResources: [], // API calls to these coordinates will NOT activate MSALGuard
    protectedResourceMap,     // API calls to these coordinates will activate MSALGuard
    extraQueryParameters: { campaignId: 'hawaii', ui_locales: 'es' } 
}

-- app.component.ts

import { Component, OnInit } from '@angular/core';
import { BroadcastService, MsalService} from '@azure/msal-angular';
import { Logger, CryptoUtils } from 'msal';
import { isIE, b2cPolicies } from './app-config';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent implements OnInit {
  title = 'Azure AD B2C';
  isIframe = false;
  loggedIn = false;

  constructor(private broadcastService: BroadcastService, private authService: MsalService) { }
  
  ngOnInit() {

    this.isIframe = window !== window.parent && !window.opener;
    this.checkAccount();

    // event listeners for authentication status
    this.broadcastService.subscribe('msal:loginSuccess', (success) => {

    // We need to reject id tokens that were not issued with the default sign-in policy.
    // "acr" claim in the token tells us what policy is used (NOTE: for new policies (v2.0), use "tfp" instead of "acr")
    // To learn more about b2c tokens, visit https://docs.microsoft.com/en-us/azure/active-directory-b2c/tokens-overview
      if (success.idToken.claims['acr'] !== b2cPolicies.names.signUpSignIn) {
        window.alert("Password has been reset successfully. \nPlease sign-in with your new password");
        return this.authService.logout()
      }

      console.log('login succeeded. id token acquired at: ' + new Date().toString());
      console.log(success);

      this.checkAccount();
    });

    this.broadcastService.subscribe('msal:loginFailure', (error) => {
      console.log('login failed');
      console.log(error);

        // Check for forgot password error
        // Learn more about AAD error codes at https://docs.microsoft.com/en-us/azure/active-directory/develop/reference-aadsts-error-codes
        if (error.errorMessage.indexOf('AADB2C90118') > -1) {
          if (isIE) {
            this.authService.loginRedirect(b2cPolicies.authorities.resetPassword);
          } else {
            this.authService.loginPopup(b2cPolicies.authorities.resetPassword);
          }
        }
    });

    // redirect callback for redirect flow (IE)
    this.authService.handleRedirectCallback((authError, response) => {
      if (authError) {
        console.error('Redirect Error: ', authError.errorMessage);
        return;
      }

      console.log('Redirect Success: ', response);
    });

    this.authService.setLogger(new Logger((logLevel, message, piiEnabled) => {
      console.log('MSAL Logging: ', message);
    }, {
      correlationId: CryptoUtils.createNewGuid(),
      piiLoggingEnabled: false
    }));
  }

  // other methods
  checkAccount() {
    this.loggedIn = !!this.authService.getAccount();
  }

  login() {
    if (isIE) {
      this.authService.loginRedirect();
    } else {
      this.authService.loginPopup();
    }
  }

  logout() {
    this.authService.logout();
  }
}

state 是你应该使用的。

https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-js-pass-custom-state-authentication-request

The state parameter, as defined by OAuth 2.0, is included in an authentication request and is also returned in the token response to prevent cross-site request forgery attacks. By default, Microsoft Authentication Library for JavaScript (MSAL.js) passes a randomly generated unique state parameter value in the authentication requests.

The state parameter can also be used to encode information of the app's state before redirect. You can pass the user's state in the app, such as the page or view they were on, as input to this parameter. The MSAL.js library allows you to pass your custom state as state parameter in the Request object

The passed in state is appended to the unique GUID set by MSAL.js when sending the request. When the response is returned, MSAL.js checks for a state match and then returns the custom passed in state in the Response object as accountState.

let loginRequest = {
    scopes: ["user.read", "user.write"],
    state: "page_url"
}

myMSALObj.loginPopup(loginRequest);

// ...


export type AuthResponse = {
    uniqueId: string;
    tenantId: string;
    tokenType: string;
    idToken: IdToken;
    accessToken: string;
    scopes: Array<string>;
    expiresOn: Date;
    account: Account;
    accountState: string;
};