question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[BUG] Using DefaultAzureCredential, second request returns 403

See original GitHub issue

Describe the bug I’m using DefaultAzureCredential to authenticate through Azure CLI (via az login). With the azure-storage-blob SDK I can complete one GET operation, but any subsequent GETs return a 403.

Exception or Stack Trace

com.azure.storage.blob.models.BlobContainerItem@a1f72f5
Exception in thread "main" com.azure.storage.blob.models.BlobStorageException: Status code 403, "<?xml version="1.0" encoding="utf-8"?><Error><Code>AuthorizationPermissionMismatch</Code><Message>This request is not authorized to perform this operation using this permission.
RequestId:d509520c-d01e-00a8-6cdb-09ef73000000
Time:2020-04-03T17:12:28.6748208Z</Message></Error>"
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at com.azure.core.http.rest.RestProxy.instantiateUnexpectedException(RestProxy.java:357)
	at com.azure.core.http.rest.RestProxy.lambda$ensureExpectedStatus$3(RestProxy.java:400)
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:118)
	at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1592)
	at reactor.core.publisher.MonoProcessor.onNext(MonoProcessor.java:317)
	at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2148)
	at reactor.core.publisher.MonoProcessor.onSubscribe(MonoProcessor.java:325)
	at reactor.core.publisher.FluxFlatMap.trySubscribeScalarMap(FluxFlatMap.java:191)
	at reactor.core.publisher.MonoFlatMap.subscribeOrReturn(MonoFlatMap.java:53)
	at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:48)
	at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
	at reactor.core.publisher.Mono.subscribe(Mono.java:4087)
	at reactor.core.publisher.MonoProcessor.add(MonoProcessor.java:457)
	at reactor.core.publisher.MonoProcessor.subscribe(MonoProcessor.java:370)
	at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:55)
	at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:150)
	at reactor.core.publisher.FluxDoFinally$DoFinallySubscriber.onNext(FluxDoFinally.java:123)
	at reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:112)
	at reactor.core.publisher.FluxMap$MapConditionalSubscriber.onNext(FluxMap.java:213)
	at reactor.core.publisher.FluxDoFinally$DoFinallySubscriber.onNext(FluxDoFinally.java:123)
	at reactor.core.publisher.FluxHandleFuseable$HandleFuseableSubscriber.onNext(FluxHandleFuseable.java:178)
	at reactor.core.publisher.FluxContextStart$ContextStartSubscriber.onNext(FluxContextStart.java:103)
	at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1592)
	at reactor.core.publisher.MonoCollectList$MonoCollectListSubscriber.onComplete(MonoCollectList.java:121)
	at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:252)
	at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:136)
	at reactor.netty.channel.FluxReceive.terminateReceiver(FluxReceive.java:419)
	at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:209)
	at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:367)
	at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:363)
	at reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:412)
	at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:572)
	at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:90)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355)
	at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:316)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290)
	at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355)
	at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1470)
	at io.netty.handler.ssl.SslHandler.decodeNonJdkCompatible(SslHandler.java:1231)
	at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1268)
	at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:493)
	at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:432)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:271)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:355)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:377)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.lang.Thread.run(Thread.java:748)

To Reproduce az login

public class AzLogin {
    public static void main(String[] args) {
        final String endpoint = "https://mystorageaccount.blob.core.windows.net";
        final String container = "mycontainer";
        final String prefix = "customer";

        DefaultAzureCredential creds = new DefaultAzureCredentialBuilder().build();

        final BlobServiceClientBuilder clientBuilder = new BlobServiceClientBuilder();
        clientBuilder.endpoint(endpoint);
        clientBuilder.credential(creds);

        BlobServiceClient client = clientBuilder.buildClient();

        // This works
        client.listBlobContainers().forEach(System.out::println);

        BlobContainerClient blobContainerClient = client.getBlobContainerClient(container);

        ListBlobsOptions blobOptions = new ListBlobsOptions().setPrefix(prefix);

        // This and other requests return 403
        blobContainerClient.listBlobs(blobOptions, Duration.ofSeconds(60)).forEach(BlobItem::getName);

    }
}

Expected behavior I’d expect that once setup, all requests would be authenticated, not just the first. Setup (please complete the following information):

  • OS: Mac OS 10.15.4
  • IDE : IntelliJ
  • Version of the Library used: Java azure-identity 1.1.0-beta.2
  • Java version: AdoptJDK 1.8.0-212

Additional context Authenticating using a StorageSharedKeyCredential (storage account name, key) in BlobServiceClientBuilder works fine, so I don’t believe it’s a matter of blob permissions (also this account has no special permissions applied).

Information Checklist Kindly make sure that you have added all the following information above and checkoff the required fields otherwise we will treat the issuer as an incomplete report

  • Bug Description Added
  • Repro Steps Added
  • Setup information Added

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
rothwerxcommented, Apr 14, 2020

Ah, you’re right. I didn’t understand that it would need the Azure AD Authentication Method instead of the Access Key method as explained here https://docs.microsoft.com/en-us/azure/storage/common/storage-access-blobs-queues-portal

I gave my account Reader and Storage Blob Data Reader roles and after a few minutes I was able to list blobs in my storage account, having authenticated with az login previously. Sorry for the noise.

0reactions
alzimmermsftcommented, Apr 14, 2020

@rothwerx, what permissions does the account/identity have in the Storage service?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Troubleshoot Azure Digital Twins: Error 403 (Forbidden)
This article describes causes and resolution steps for receiving a 403 error from service requests to Azure Digital Twins.
Read more >
Creating Workitem thru api failing with 403 Forbidden status ...
I am facing a problem that my request to create a workitem (bug, task, user story) is failing with the 403 forbidden status...
Read more >
403 Forbidden Error: What It Is and How to Fix It - Airbrake Blog
A detailed explanation of what a 403 Forbidden Error response is, including troubleshooting tips to help you resolve this error.
Read more >
403 when connecting to Azure App Configuration using a ...
This document demonstrates how to use managed identity to access App Configuration from App Service, but you can replace the App Service ...
Read more >
How to Fix a 403 Forbidden Error on Your WordPress Site
The 403 Forbidden error indicates that the server understood the request but refuses to authorize it. Find out more about the causes and ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found