Error when attempting to use `InteractiveBrowserCredential` for downloading from blob storage
See original GitHub issue- Package Name:
@azure/identity
- Package Version:
2.0.0-beta.6
- Package Name:
@azure/storage-blob
- Package Version:
^12.11.0
- Operating system: OSX
- nodejs
- version:
^13.7.0
- version:
- browser
- name/version:
- typescript
- version:
~4.6.2
- version:
- Is the bug related to documentation in
- README.md
- source code documentation
- SDK API docs on https://docs.microsoft.com
Describe the bug
We’re seeing the following error in the terminal when we attempt to use the InteractiveBrowserCredential
class to authorize a script to download files from blob storage for the user.
Error: Interactive Browser Authentication Error “Did not receive token with a valid expiration”
At the same time, we see this error in the browser which opens for the interactive authentication:
ERROR. Scopes: https://storage.azure.com/.default. Error message: null. null.
A simplified example of the code that is producing this error would be the following function that downloads a blob to a given directory then returns the path to that directory as a string:
export async function downloadOurSdk(version: string, downloadDirectory: string): Promise<string> {
const credential = new InteractiveBrowserCredential({
tenantId: '<redacted>',
clientId: '<redacted>',
loginStyle: 'redirect',
redirectUri: 'http://localhost:8080/',
});
const blobServiceClient = new BlobServiceClient('https://<redacted>.blob.core.windows.net', credential);
const containerClient = blobServiceClient.getContainerClient(version);
const blockBlobClient = containerClient.getBlockBlobClient('our-sdk.zip');
await blockBlobClient.downloadToFile(downloadDirectory, 0, undefined);
console.log('\nDownloaded blob content...');
return downloadDirectory;
}
The error appears to be thrown by the call to await blockBlobClient.donwloadToFile(downloadDirectory, 0, undefined);
because the console.log
after that line is never seen in the terminal (while a console.log
placed directly before that line is printed to the terminal).
I haven’t been able to find much of anything about this error online, so I’ve been reading all the documentation about the InteractiveBrowserCredential class, the InteractiveBrowserCredentialNodeOptions interface, the BlockBlobClient class’s downloadToFile method, and the BlobDownloadOptions interface, but I don’t see any mention of an expiration or timeout property in any of them (though that may be a red herring).
I’m not really sure what steps to take next, and I was hoping y’all might be able to catch something obvious that I missed about this. Note that I have also followed the instructions here to enable verbose logging, and I’ve attached the output of that at the end of this issue.
Thanks for any assistance you can give!
To Reproduce Steps to reproduce the behavior:
- Use an
InteractiveBrowserCredential
to acquire aBlobServiceClient
(using the@azure/storage-blob
package). - Use the
BlobServiceClient
to obtain aContainerClient
. - Use the
ContainerClient
to obtain aBlockBlobClient
. - Call the
BlockBlobClient
’sdownloadToFile
method.
Expected behavior
The Microsoft credentials used to login with the InteractiveBrowserCredential
should be used to authorize downloading the given blob to a file in the given directory.
Screenshots n/a
Additional context
--verbose
logs from the given error:
azure:core-client:warning The baseUri option for SDK Clients has been deprecated, please use endpoint instead.
azure:core-http:info ServiceClient: using custom request policies
azure:core-http:info ServiceClient: using custom request policies
azure:core-http:info ServiceClient: using custom request policies
azure:storage-blob:info RetryPolicy: =====> Try=1 Primary
azure:storage-blob:info Request: {
"streamResponseStatusCodes": {},
"url": "https://harborsdkbinaries.blob.core.windows.net/2-8-1-18-74105c96-osx/harbor-sdk.zip",
"method": "GET",
"headers": {
"_headersMap": {
"x-ms-version": "2021-08-06",
"accept": "application/xml",
"user-agent": "azsdk-js-storageblob/12.11.0 (NODE-VERSION v18.2.0; Darwin 21.6.0)",
"x-ms-client-request-id": "cb0f50e4-ee40-4eda-9639-67c58b069179"
}
},
"withCredentials": false,
"timeout": 0,
"keepAlive": true,
"requestId": "cb0f50e4-ee40-4eda-9639-67c58b069179"
}
azure:identity:info InteractiveBrowserCredential => MSAL Node V2 info message: [Thu, 25 Aug 2022 18:58:15 GMT] : @azure/msal-node@1.12.1 : Info - getTokenCache called
azure:identity:info Node.js MSAL Open Browser => More than one account was found authenticated for this Client ID and Tenant ID.
However, no "authenticationRecord" has been provided for this credential,
therefore we're unable to pick between these accounts.
A new login attempt will be requested, to ensure the correct account is picked.
To work with multiple accounts for the same Client ID and Tenant ID, please provide an "authenticationRecord" when initializing a credential to prevent this from happening.
azure:identity:info Node.js MSAL Open Browser => Silent authentication failed, falling back to interactive method.
azure:identity:info Node.js MSAL Open Browser => InteractiveBrowserCredential listening on port 8080!
azure:identity:info InteractiveBrowserCredential => MSAL Node V2 info message: [Thu, 25 Aug 2022 18:58:15 GMT] : @azure/msal-node@1.12.1 : Info - getAuthCodeUrl called
azure:core-rest-pipeline retryPolicy:info Retry 0: Attempting to send request 36fae5c9-01d4-4ae2-9ada-08d611d802f9
azure:core-rest-pipeline:info Request: {
"url": "https://login.microsoftonline.com/common/discovery/instance?api-version=1.1&authorization_endpoint=REDACTED",
"headers": {
"accept-encoding": "gzip,deflate",
"user-agent": "azsdk-js-identity/2.0.0-beta.6 core-rest-pipeline/1.9.1 Node/v18.2.0 OS/(x64-Darwin-21.6.0)",
"x-ms-client-request-id": "36fae5c9-01d4-4ae2-9ada-08d611d802f9"
},
"method": "GET",
"timeout": 0,
"disableKeepAlive": false,
"withCredentials": false,
"abortSignal": {},
"requestId": "36fae5c9-01d4-4ae2-9ada-08d611d802f9",
"allowInsecureConnection": false,
"enableBrowserStreams": false
}
azure:core-rest-pipeline:info No cached TLS Agent exist, creating a new Agent
azure:core-rest-pipeline:info Response status code: 200
azure:core-rest-pipeline:info Headers: {
"cache-control": "max-age=86400, private",
"content-type": "application/json; charset=utf-8",
"strict-transport-security": "max-age=31536000; includeSubDomains",
"x-content-type-options": "nosniff",
"access-control-allow-origin": "*",
"access-control-allow-methods": "GET, OPTIONS",
"p3p": "CP=\"DSP CUR OTPi IND OTRi ONL FIN\"",
"x-ms-request-id": "ed593fac-641e-4e4b-bf2c-696cf8f29000",
"x-ms-ests-server": "2.1.13481.11 - SCUS ProdSlices",
"x-xss-protection": "0",
"set-cookie": "fpc=Aq-ZappgSQpPmzILacS8OEI; expires=Sat, 24-Sep-2022 18:58:16 GMT; path=/; secure; HttpOnly; SameSite=None",
"date": "Thu, 25 Aug 2022 18:58:16 GMT",
"content-length": "980"
}
azure:core-rest-pipeline retryPolicy:info Retry 0: Received a response from request 36fae5c9-01d4-4ae2-9ada-08d611d802f9
azure:core-rest-pipeline retryPolicy:info Retry 0: Processing 2 retry strategies.
azure:core-rest-pipeline retryPolicy:info Retry 0: Processing retry strategy throttlingRetryStrategy.
azure:core-rest-pipeline retryPolicy:info Retry 0: Skipped.
azure:core-rest-pipeline retryPolicy:info Retry 0: Processing retry strategy exponentialRetryStrategy.
azure:core-rest-pipeline retryPolicy:info Retry 0: Skipped.
azure:core-rest-pipeline retryPolicy:info None of the retry strategies could work with the received response. Returning it.
azure:core-rest-pipeline retryPolicy:info Retry 0: Attempting to send request 927305c4-23e9-4b13-af1b-661045c0b274
azure:core-rest-pipeline:info Request: {
"url": "https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47/v2.0/.well-known/openid-configuration",
"headers": {
"accept-encoding": "gzip,deflate",
"user-agent": "azsdk-js-identity/2.0.0-beta.6 core-rest-pipeline/1.9.1 Node/v18.2.0 OS/(x64-Darwin-21.6.0)",
"x-ms-client-request-id": "927305c4-23e9-4b13-af1b-661045c0b274"
},
"method": "GET",
"timeout": 0,
"disableKeepAlive": false,
"withCredentials": false,
"abortSignal": {},
"requestId": "927305c4-23e9-4b13-af1b-661045c0b274",
"allowInsecureConnection": false,
"enableBrowserStreams": false
}
azure:core-rest-pipeline:info Response status code: 200
azure:core-rest-pipeline:info Headers: {
"cache-control": "max-age=86400, private",
"content-type": "application/json; charset=utf-8",
"strict-transport-security": "max-age=31536000; includeSubDomains",
"x-content-type-options": "nosniff",
"access-control-allow-origin": "*",
"access-control-allow-methods": "GET, OPTIONS",
"p3p": "CP=\"DSP CUR OTPi IND OTRi ONL FIN\"",
"x-ms-request-id": "27228cfa-649f-4a09-9007-6d20fffd4200",
"x-ms-ests-server": "2.1.13481.12 - SCUS ProdSlices",
"x-xss-protection": "0",
"set-cookie": "fpc=AnGD6erPafxDm5xhJ2FGGQU; expires=Sat, 24-Sep-2022 18:58:16 GMT; path=/; secure; HttpOnly; SameSite=None",
"date": "Thu, 25 Aug 2022 18:58:16 GMT",
"content-length": "1753"
}
azure:core-rest-pipeline retryPolicy:info Retry 0: Received a response from request 927305c4-23e9-4b13-af1b-661045c0b274
azure:core-rest-pipeline retryPolicy:info Retry 0: Processing 2 retry strategies.
azure:core-rest-pipeline retryPolicy:info Retry 0: Processing retry strategy throttlingRetryStrategy.
azure:core-rest-pipeline retryPolicy:info Retry 0: Skipped.
azure:core-rest-pipeline retryPolicy:info Retry 0: Processing retry strategy exponentialRetryStrategy.
azure:core-rest-pipeline retryPolicy:info Retry 0: Skipped.
azure:core-rest-pipeline retryPolicy:info None of the retry strategies could work with the received response. Returning it.
azure:identity:info InteractiveBrowserCredential => MSAL Node V2 info message: [Thu, 25 Aug 2022 18:58:17 GMT] : @azure/msal-node@1.12.1 : Info - acquireTokenByCode called
azure:identity:info InteractiveBrowserCredential => MSAL Node V2 info message: [Thu, 25 Aug 2022 18:58:17 GMT] : [6171d1d6-3c74-455c-8364-a9078fea62b7] : @azure/msal-common@7.3.0 : Info - in acquireToken call
azure:core-rest-pipeline retryPolicy:info Retry 0: Attempting to send request e3d911d9-0c4f-43a4-acac-19f5ffca512a
azure:core-rest-pipeline:info Request: {
"url": "https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47/oauth2/v2.0/token",
"headers": {
"content-type": "application/x-www-form-urlencoded;charset=utf-8",
"accept-encoding": "gzip,deflate",
"user-agent": "azsdk-js-identity/2.0.0-beta.6 core-rest-pipeline/1.9.1 Node/v18.2.0 OS/(x64-Darwin-21.6.0)",
"x-ms-client-request-id": "e3d911d9-0c4f-43a4-acac-19f5ffca512a"
},
"method": "POST",
"timeout": 0,
"disableKeepAlive": false,
"withCredentials": false,
"abortSignal": {},
"requestId": "e3d911d9-0c4f-43a4-acac-19f5ffca512a",
"allowInsecureConnection": false,
"enableBrowserStreams": false
}
azure:core-rest-pipeline:info Response status code: 400
azure:core-rest-pipeline:info Headers: {
"cache-control": "no-store, no-cache",
"pragma": "no-cache",
"content-type": "application/json; charset=utf-8",
"expires": "-1",
"strict-transport-security": "max-age=31536000; includeSubDomains",
"x-content-type-options": "nosniff",
"p3p": "CP=\"DSP CUR OTPi IND OTRi ONL FIN\"",
"x-ms-request-id": "48444501-1d77-4280-ae65-7c5b5c130100",
"x-ms-ests-server": "2.1.13672.0 - CHY FirstSlice",
"x-ms-clitelem": "1,9002327,0,,I",
"x-xss-protection": "0",
"set-cookie": "fpc=Ah_S4yGIGwVDn7N-J4rczGaYKMIdAQAAAEm9mdoOAAAA; expires=Sat, 24-Sep-2022 18:58:18 GMT; path=/; secure; HttpOnly; SameSite=None",
"date": "Thu, 25 Aug 2022 18:58:18 GMT",
"content-length": "478"
}
azure:core-rest-pipeline retryPolicy:info Retry 0: Received a response from request e3d911d9-0c4f-43a4-acac-19f5ffca512a
azure:core-rest-pipeline retryPolicy:info Retry 0: Processing 2 retry strategies.
azure:core-rest-pipeline retryPolicy:info Retry 0: Processing retry strategy throttlingRetryStrategy.
azure:core-rest-pipeline retryPolicy:info Retry 0: Skipped.
azure:core-rest-pipeline retryPolicy:info Retry 0: Processing retry strategy exponentialRetryStrategy.
azure:core-rest-pipeline retryPolicy:info Retry 0: Skipped.
azure:core-rest-pipeline retryPolicy:info None of the retry strategies could work with the received response. Returning it.
azure:identity:info Node.js MSAL Open Browser => getToken() => ERROR. Scopes: https://storage.azure.com/.default. Error message: null. null.
azure:storage-blob:error RetryPolicy: Caught error, message: Interactive Browser Authentication Error "Did not receive token with a valid expiration", code: undefined
harbor-install Invocation Failed:
Error: Interactive Browser Authentication Error "Did not receive token with a valid expiration"
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Issue Analytics
- State:
- Created a year ago
- Comments:11 (5 by maintainers)
Ah I think I see the shape of this a bit better. Am I correct in understanding you are building a command-line tool that can download a blob using the user’s credentials?
DefaultAzureCredential
is magical when it works, though it does require some form of active identity present on the machine. Managed Identity is more about authenticating a deployed service without extra configuration than it is about authenticating a local user against AAD, so I’m not sure how useful it will be if I understand your use-case.Until WAM is supported, you’re probably right that
InteractiveBrowserCredential
is the “correct” flow for your use case, though the app registration bits make it complex. @schaabs do you have any advice here?I spent a bit of time trying to repro this so I could debug it, but I can’t seem to get past this blocker:
Whenever I have my app request user_impersonation of storage it claims it needs admin consent… even though I can’t see any reason why it should. Using other kinds of AAD auth (e.g.
EnvironmentCredential
with that same app using a secret) works great.