AzureAD / microsoft-authentication-library-for-js

Microsoft Authentication Library (MSAL) for JS
http://aka.ms/aadv2
MIT License
3.67k stars 2.65k forks source link

acquireTokenSilent : ERROR InteractionRequiredAuthError: no_tokens_found: No refresh token found in the cache. Please sign-in #7303

Open AdzeB opened 2 months ago

AdzeB commented 2 months ago

Core Library

MSAL Node (@azure/msal-node)

Core Library Version

2.13.1

Wrapper Library

Not Applicable

Wrapper Library Version

N/A

Public or Confidential Client?

Public

Description

We are calling acquireTokenSilent to get a new token without needing the user to give permissions again, but the function throws the error acquireTokenSilent : ERROR InteractionRequiredAuthError: no_tokens_found: No refresh token found in the cache. Please sign-in

Error Message

Error silently: InteractionRequiredAuthError: no_tokens_found: No refresh token found in the cache. Please sign-in.

MSAL Logs

[Tue, 10 Sep 2024 19:11:02 GMT] : [] : @azure/msal-common@14.14.2 : Info - CacheManager:getIdToken - Returning ID token
[Tue, 10 Sep 2024 19:11:02 GMT] : [edf00ed8-1a30-462a-b1da-04e9ac1bb8e5] : @azure/msal-node@2.13.1 : Info - Building oauth client configuration with the following authority: https://login.microsoftonline.com/TENANT_I/oauth2/v2.0/token.
[Tue, 10 Sep 2024 19:11:02 GMT] : [edf00ed8-1a30-462a-b1da-04e9ac1bb8e5] : @azure/msal-common@14.14.2 : Info - Token refresh is required due to cache outcome: 1
[Tue, 10 Sep 2024 19:11:02 GMT] : [] : @azure/msal-common@14.14.2 : Info - CacheManager:getRefreshToken - No refresh token found.
Error silently: InteractionRequiredAuthError: no_tokens_found: No refresh token found in the cache. Please sign-in.

Network Trace (Preferrably Fiddler)

MSAL Configuration

export const msalConfig = (
  supabase: SupabaseClient,
  userId: string,
): Configuration => {
  return {
    auth: {
      clientId: process.env.OUTLOOK_CLIENT_ID || "",
      clientSecret: process.env.OUTLOOK_CLIENT_SECRET,
      authority:
        `https://login.microsoftonline.com/${process.env.OUTLOOK_TENANT_ID}`,
    },
    cache: {
      cachePlugin: new SupabaseCachePlugin(supabase, userId),
    },
    system: {
      loggerOptions: {
        loggerCallback(
          loglevel: LogLevel,
          message: string,
          containsPii: boolean,
        ) {
          console.log(message);
        },
        piiLoggingEnabled: false,
        logLevel: LogLevel.Info,
      },
    },
  };
};

Relevant Code Snippets

export class SupabaseCachePlugin implements ICachePlugin {
  private supabase: SupabaseClient;
  private userId: string;

  constructor(supabase: SupabaseClient, userId: string) {
    this.supabase = supabase;
    this.userId = userId;
  }

  async beforeCacheAccess(cacheContext: TokenCacheContext): Promise<void> {
    // Load the cache from Supabase for the specific user

    console.log("beforeCacheAccess", cacheContext);
    const { data, error } = await this.supabase
      .from("msal_cache")
      .select("cache_data")
      .eq("user_id", this.userId)
      .single();

    if (data && !error) {
      cacheContext.tokenCache.deserialize(data.cache_data);
    }
  }

  async afterCacheAccess(cacheContext: TokenCacheContext): Promise<void> {
    if (cacheContext.cacheHasChanged) {
      // Save the updated cache to Supabase for the specific user
      const serializedCache = cacheContext.tokenCache.serialize();
      await this.supabase
        .from("msal_cache")
        .upsert({
          user_id: this.userId,
          cache_data: serializedCache,
        });
    }
  }
}

Reproduction Steps

  1. Successful login using the following scope ["openid","profile","Calendars.Read","Calendars.ReadWrite", "email","user.read","offline_access"]
  2. Call AcquireTokenSilent function

Expected Behavior

we should be able to get a new token.

Identity Provider

Entra ID (formerly Azure AD) / MSA

Browsers Affected (Select all that apply)

None (Server)

Regression

N/A

Source

External (Customer)

sameerag commented 1 month ago

cc @Robbie-Microsoft @bgavrilMS

altinokdarici commented 1 month ago

@Robbie-Microsoft @bgavrilMS could you help here? We are hitting the same issue. (not sure if the root causes are the same or different) I wonder if it could be related to a recent code change or something on msal side?

altinokdarici commented 1 month ago

In our setup, We have a nodejs app and we use InteractiveBrowserCredential from @azure/identity along with @azure/identity-cache-persistence. We don't implement any custom cache plugin in our code.

Here is my call stack (it might be irrelevant since it's bundled but it might help with the class/fn names.)

InteractionRequiredAuthError: no_tokens_found: No refresh token found in the cache. Please sign-in.
    at createInteractionRequiredAuthError (getCredential-QYKZSYTT.js:6046:10)
    at _RefreshTokenClient.acquireTokenWithCachedRefreshToken (getCredential-QYKZSYTT.js:7082:17)
    at getCredential-QYKZSYTT.js:2019:16
    at _RefreshTokenClient.acquireTokenByRefreshToken (getCredential-QYKZSYTT.js:7071:211)
    at async withSilentAuthentication (getCredential-QYKZSYTT.js:17186:22)
    at async (getCredential-QYKZSYTT.js:18751:11)
    at async Object.withSpan (chunk-FUS4SMZ3.js:552:26)
    at async getCredential (getCredential-QYKZSYTT.js:19923:32)
error Command failed with exit code 1.
bgavrilMS commented 1 month ago

InteractiveBrowserCredential is a public client scenario and @Robbie-Microsoft and I don't own this scenario.

Updating the issue.

CC @peterzenz

AdzeB commented 1 month ago

Why was this clsoe?

mryraghi commented 1 month ago

I'm sickened by the awful developer experience in dealing with Microsoft and Azure.

bgavrilMS commented 1 month ago

@AdzeB - how do you get the first set of tokens? Do you use AcquireTokenByAuthCode?

AdzeB commented 1 month ago

Hi @bgavrilMS  I used getAuthCodeUrl

const authCodeUrlParameters: AuthorizationUrlRequest = {  
       scopes: OUTLOOK\_SCOPES,  
       redirectUri: redirectUri,  
       // prompt: "consent", // Force a new consent prompt  
       // extraQueryParameters: {  
       //   response\_mode: "query", // Ensures compatibility with various OAuth flows  
       // },  
       responseMode: "query",  
       prompt: "consent", // Force a new consent prompt  
       extraQueryParameters: {  
         response\_mode: "query",  
         access: "offline", // Explicitly request offline access  
       },  
     };

// Generate the authorization URL  
const authUrl = await getMsalClient(supabase, userId).getAuthCodeUrl(  
     authCodeUrlParameters,  
);  
console.log("alok", authUrl);  
return authUrl;
export function getMsalClient(supabase: SupabaseClient, userId: string) {

return new ConfidentialClientApplication(msalConfig(supabase, userId));

}
WiktorHeimroth commented 3 weeks ago

Seeing the same issue when using msal-node. Acquiring first token with acquireTokenByCode is successful but when i try to use acquireTokenSilent with the same scope and account object that i recieved from acquireTokenByCode response im seeing this error: image

Robbie-Microsoft commented 3 weeks ago

Folks, I'm not able to reproduce this error. Via our msal-node Silent Flow sample, I plugged in my own clientId and used a clientCertificate (thumbprint + private key) instead of clientSecret on lines 236-240 in index.js. I used msal-node v2.13.1 like specified above.

bgavrilMS commented 2 weeks ago

It would be helpful to a have a minimal bug repro to work on.

WiktorHeimroth commented 2 weeks ago

Core Library

MSAL Node (@azure/msal-node)

Core Library Version 2.15.0

Wrapper Library Not Applicable

Wrapper Library Version N/A

Public or Confidential Client? Confidential

Description Acquiring first token with acquireTokenByCode is successful but when trying to use acquireTokenSilent with the same scope and account object that i recieved from acquireTokenByCode response im seeing this error.

Error Message

[InteractionRequiredAuthError: no_tokens_found: No refresh token found in the cache. Please sign-in.] { errorCode: 'no_tokens_found', errorMessage: 'No refresh token found in the cache. Please sign-in.', subError: '', name: 'InteractionRequiredAuthError', timestamp: '', traceId: '', correlationId: '31fccaf9-c819-4c7f-8514-1cb3462ce8fb', claims: '', errorNo: undefined }

MSAL Logs

[Mon, 28 Oct 2024 12:16:01 GMT] : [] : @azure/msal-node@2.15.0 : Verbose - initializeRequestScopes called [Mon, 28 Oct 2024 12:16:01 GMT] : [31fccaf9-c819-4c7f-8514-1cb3462ce8fb] : @azure/msal-node@2.15.0 : Verbose - buildOauthClientConfiguration called [Mon, 28 Oct 2024 12:16:01 GMT] : [31fccaf9-c819-4c7f-8514-1cb3462ce8fb] : @azure/msal-node@2.15.0 : Verbose - createAuthority called [Mon, 28 Oct 2024 12:16:01 GMT] : [] : @azure/msal-node@2.15.0 : Verbose - Attempting to get cloud discovery metadata from authority configuration [Mon, 28 Oct 2024 12:16:01 GMT] : [] : @azure/msal-node@2.15.0 : Verbose - Did not find cloud discovery metadata in the config... Attempting to get cloud discovery metadata from the hardcoded values.
[Mon, 28 Oct 2024 12:16:01 GMT] : [] : @azure/msal-node@2.15.0 : Verbose - Found cloud discovery metadata from hardcoded values. [Mon, 28 Oct 2024 12:16:01 GMT] : [] : @azure/msal-node@2.15.0 : Verbose - Attempting to get endpoint metadata from authority configuration [Mon, 28 Oct 2024 12:16:01 GMT] : [] : @azure/msal-node@2.15.0 : Verbose - Did not find endpoint metadata in the config... Attempting to get endpoint metadata from the hardcoded values. [Mon, 28 Oct 2024 12:16:01 GMT] : [] : @azure/msal-node@2.15.0 : Verbose - Replacing tenant domain name with id {tenantid} [Mon, 28 Oct 2024 12:16:01 GMT] : [31fccaf9-c819-4c7f-8514-1cb3462ce8fb] : @azure/msal-node@2.15.0 : Info - Building oauth client configuration with the following authority: https://login.microsoftonline.com/tenant-id/oauth2/v2.0/token. [Mon, 28 Oct 2024 12:16:01 GMT] : [31fccaf9-c819-4c7f-8514-1cb3462ce8fb] : @azure/msal-node@2.15.0 : Verbose - Silent flow client created [Mon, 28 Oct 2024 12:16:01 GMT] : [] : @azure/msal-common@14.15.0 : Info - CacheManager:getAccessToken - No token found [Mon, 28 Oct 2024 12:16:01 GMT] : [31fccaf9-c819-4c7f-8514-1cb3462ce8fb] : @azure/msal-common@14.15.0 : Info - Token refresh is required due to cache outcome: 2 [Mon, 28 Oct 2024 12:16:01 GMT] : [] : @azure/msal-common@14.15.0 : Info - CacheManager:getRefreshToken - No refresh token found.

MSAL Configuration const msalConfig = { auth: { clientId: process.env.AZURE_AD_CLIENT_ID, authority: https://login.microsoftonline.com/${process.env.AZURE_AD_TENANT_ID}, clientSecret: process.env.AZURE_AD_SECRET, }, cache: { cacheLocation: "localStorage" }, system: { loggerOptions: { logLevel: msal.LogLevel.Verbose, loggerCallback: (level: any, message: any, containsPii: any) => { if (containsPii) { return; } switch (level) { case msal.LogLevel.Error: console.error(message); return; case msal.LogLevel.Info: console.info(message); return; case msal.LogLevel.Verbose: console.debug(message); return; case msal.LogLevel.Warning: console.warn(message); return; } }, piiLoggingEnabled: false, }, }, };

Reproduction Steps This is happening inside next.js 13 API Routes

  1. Successful login using acquireTokenByCode function with following scope const scope = ['openid', 'api://client-id/app-name']

  2. Call AcquireTokenSilent

Expected Behavior we should be able to get a new token.

Identity Provider Entra ID

WiktorHeimroth commented 1 week ago

Hi, any updates/fixes on the issue above?

bgavrilMS commented 1 week ago

Sorry, the bot keeps closing it this.

bgavrilMS commented 1 week ago

Folks, we have not been able to reproduce this issue. Can someone please provide a minimal repo? I can see in the original post a custom cache, it's not enough to repro. Could someone pls create a small sample that reproduces the issue?

AdzeB commented 1 week ago

@bgavrilMS How you like the sample to work, would you like it with supabase etc set up…you just need to enter the keys?

bgavrilMS commented 5 days ago

We can provision our own Entra ID app, redirect URI, secret etc.