'Accessing Azure Blob via a Registered App Using Tokens

I'm new to Azure and I'm struggling to get a simple demo working.

I'm trying to write a daemon client that accesses a blob. The access must be via a registered app, and I want to explicitly acquire an access token.

As a warm-up I wrote a demo that accesses the blob using the blob api, and this works OK:

ClientCertificateCredential credentials = new ClientCertificateCredentialBuilder()
        .clientId("11518eab-7b5a-493c-8d12-27731fe51341")
        .tenantId("4b106bc5-7518-4f86-a259-f5726d124732")
        .pemCertificate("/home/william/cert/new/azure.pem")
        .build();
    
BlobServiceClient blobServiceClient = new BlobServiceClientBuilder()
        .credential(credentials)
        .endpoint("https://wemsa.blob.core.windows.net/")
        .buildClient();
    
BlobContainerClient blobContainerClient = blobServiceClient.getBlobContainerClient("wemco");
     
blobContainerClient.getBlobClient("spiral.jpeg")
        .downloadToFile("/home/william/blob.jpeg");

The above code uses my registered app to create a BlobClient that downloads my blob file. The fact that this works shows me that my app does have the role required to access my storage container.

I want to create a second demo that does the same thing, but I want to get an access token explicitly and use it to authorise a plain http request to the blob api. So far this is what I've produced:

private static final String TENANT_ID = "4b106bc5-7518-4f86-a259-f5726d124732";
private static final String CLIENT_ID = "11518eab-7b5a-493c-8d12-27731fe51341";
private static final String AUTHORITY = "https://login.microsoftonline.com/" + TENANT_ID;
private static final Set<String> SCOPE = Collections.singleton("api://" + CLIENT_ID + "/.default");


InputStream pkcs12Cert = new FileInputStream("/home/william/cert/new/azure.p12");
String certPwd = "password123";
IClientCredential credential = ClientCredentialFactory.createFromCertificate(pkcs12Cert, certPwd);

ConfidentialClientApplication cca = ConfidentialClientApplication
        .builder(CLIENT_ID, credential).authority(AUTHORITY).build();

ClientCredentialParameters parameters = ClientCredentialParameters.builder(SCOPE).build();

IAuthenticationResult result = cca.acquireToken(parameters).join();
String token = result.accessToken();

URI uri = new URI("https://wemsa.blob.core.windows.net/wemco/spiral.jpeg");

HttpClient httpClient = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
        .uri(uri)
        .header("Authorization", "Bearer " + token)
        .header("Date",           formatNow())
        .header("x-ms-version",  "2020-06-12")
        .GET()
        .build();

HttpResponse<String> response = httpClient.send(request, BodyHandlers.ofString());

System.out.println(response.statusCode()); // 401 !!!

This uses the same registered app as the first demo. Debugging tells me that it is successfully getting access tokens. But, when I try to use them I always get a 401 response. I had hoped that since the first demo works OK, the second demo would automatically work as well - but it doesn't.

  • Is what I'm trying to do even possible?
  • Is there something wrong with the code in my second demo?
  • Do I need to do more setup in Azure before demo 2 will work? Some of the Azure docs mention creating an app role, which I tried, but I didn't know what to do with it.

Any suggestions ?


Additional info: This is what I did in Azure (accepting defaults for everything):

  • create storage account wemsa
  • create container wemco inside wemsa
  • upload (a small) file 'spiral.jpeg' into container wemco
  • create app registration wemapp
  • upload certificate 'azure.crt' into wemapp

Then I returned to the container wemco and:

  • granted role 'Storage Blob Data Contributor' to wemapp

This was enough to get demo 1 working.



Solution 1:[1]

Fixed by changing the scope (i.e. the requested resource) to azure storage:

private static final Set<String> SCOPE = 
        Collections.singleton("https://storage.azure.com//.default");

After making this change I was able to download my blob file using the demo 2 code in the original posting.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 BillyBadBoy