22// Licensed under the MIT license.
33
44import { AccountInfo , Configuration , PublicClientApplication , TokenCache } from "@azure/msal-node" ;
5- import { FxError , LogLevel , Result , SystemError , UserError , err , ok } from "@microsoft/teamsfx-api" ;
5+ import {
6+ AuthenticationWWWAuthenticateRequest ,
7+ FxError ,
8+ LogLevel ,
9+ Result ,
10+ SystemError ,
11+ UserError ,
12+ err ,
13+ ok ,
14+ } from "@microsoft/teamsfx-api" ;
615import { Mutex } from "async-mutex" ;
716import * as crypto from "crypto" ;
817import express from "express" ;
@@ -28,15 +37,9 @@ import {
2837 saveAccountId ,
2938 saveTenantId ,
3039} from "./cacheAccess" ;
31- import {
32- MFACode ,
33- azureLoginMessage ,
34- env ,
35- m365LoginMessage ,
36- sendFileTimeout ,
37- } from "./common/constant" ;
40+ import { azureLoginMessage , env , m365LoginMessage , sendFileTimeout } from "./common/constant" ;
3841import CliCodeLogInstance from "./log" ;
39- import { featureFlagManager , FeatureFlags } from "@microsoft/teamsfx-core " ;
42+ import { decodeClaimsChallenge } from "./common/utils " ;
4043
4144export class ErrorMessage {
4245 static readonly loginFailureTitle = "LoginFail" ;
@@ -106,10 +109,22 @@ export class CodeFlowLogin {
106109 }
107110 }
108111
109- async login ( scopes : Array < string > , tenantId ?: string ) : Promise < string > {
112+ async login (
113+ requestScopes : Array < string > | AuthenticationWWWAuthenticateRequest ,
114+ tenantId ?: string
115+ ) : Promise < string > {
110116 CliTelemetry . sendTelemetryEvent ( TelemetryEvent . AccountLoginStart , {
111117 [ TelemetryProperty . AccountType ] : this . accountName ,
112118 } ) ;
119+ let scopes : string [ ] ;
120+ let claim = undefined ;
121+ if ( typeof requestScopes === "object" && "wwwAuthenticate" in requestScopes ) {
122+ scopes = requestScopes . scopes ?? [ ] ;
123+ claim = decodeClaimsChallenge ( requestScopes . wwwAuthenticate ) ;
124+ } else {
125+ scopes = requestScopes ;
126+ }
127+
113128 const codeVerifier = CodeFlowLogin . toBase64UrlEncoding (
114129 crypto . randomBytes ( 32 ) . toString ( "base64" )
115130 ) ;
@@ -143,6 +158,7 @@ export class CodeFlowLogin {
143158 redirectUri : `http://localhost:${ serverPort } ` ,
144159 prompt : "select_account" ,
145160 authority : authority ,
161+ claims : claim ,
146162 } ;
147163
148164 let deferredRedirect : Deferred < string > ;
@@ -265,7 +281,7 @@ export class CodeFlowLogin {
265281 }
266282
267283 async getTokenByScopes (
268- scopes : Array < string > ,
284+ scopes : string | string [ ] | AuthenticationWWWAuthenticateRequest ,
269285 refresh = true ,
270286 tenantId ?: string
271287 ) : Promise < Result < string , FxError > > {
@@ -276,10 +292,23 @@ export class CodeFlowLogin {
276292 if ( ! tenantId ) {
277293 tenantId = await loadTenantId ( this . accountName ) ;
278294 }
295+
279296 if ( ! this . account ) {
280- const accessToken = await this . login ( scopes , tenantId ) ;
297+ const accessToken = await this . login (
298+ typeof scopes === "string" ? [ scopes ] : scopes ,
299+ tenantId
300+ ) ;
281301 return ok ( accessToken ) ;
282302 } else {
303+ let myScopes : string [ ] = [ ] ;
304+ if ( typeof scopes === "string" ) {
305+ myScopes = [ scopes ] ;
306+ } else if ( typeof scopes === "object" && "wwwAuthenticate" in scopes ) {
307+ myScopes = ( scopes as AuthenticationWWWAuthenticateRequest ) . scopes ?? [ ] ;
308+ } else {
309+ myScopes = scopes ;
310+ }
311+
283312 let tenantedAccount : AccountInfo | undefined = undefined ;
284313 if ( tenantId ) {
285314 const allAccounts = await this . msalTokenCache . getAllAccounts ( ) ;
@@ -289,7 +318,7 @@ export class CodeFlowLogin {
289318 try {
290319 const res = await this . pca . acquireTokenSilent ( {
291320 account : this . account ,
292- scopes : scopes ,
321+ scopes : myScopes ,
293322 forceRefresh : tenantedAccount ? false : true ,
294323 authority : tenantId
295324 ? env . activeDirectoryEndpointUrl + tenantId
@@ -313,7 +342,7 @@ export class CodeFlowLogin {
313342 }
314343 await this . logout ( ) ;
315344 if ( refresh ) {
316- const accessToken = await this . login ( scopes , tenantId ) ;
345+ const accessToken = await this . login ( myScopes , tenantId ) ;
317346 return ok ( accessToken ) ;
318347 }
319348 return err ( LoginCodeFlowError ( error ) ) ;
0 commit comments