Azure-sdk-for-js: @azure/storage-blob authentication with @azure/ms-rest-nodeauth

Created on 31 May 2019  路  6Comments  路  Source: Azure/azure-sdk-for-js

Is your feature request related to a problem? Please describe.
I'd like to login to blob storage using a service principal using @azure/ms-rest-nodeauth. For my application, I already have a service principal authenticating to retrieve secrets. Ideally, I'd use that service principal to retrieve and upload blobs.

@azure/storage-blob supports SharedKeyCredential, TokenCredential, and AnonymousCredential. In particular, a casual reader of the code might think that TokenCredential from @azure/storage-blob and TokenCredentialBase from @azure/ms-rest-nodeauth are the same until they inspect the code closely. It turns out these are not interoperable.

Describe the solution you'd like
My request is to see if it is possible to use an object produced by the @azure/ms-rest-nodeauth to authenticate with @azure/storage-blob

Describe alternatives you've considered
In my case, it is trivial to use my authenticated service principal to retrieve the blob storage key secret from Key Vault. But it feels like these two libraries should be more seamless, since the documentation points users towards the @azure/ms-rest-nodeauth library as the one stop shop for authenticating with the Azure SDK.

Client Storage customer-reported question

Most helpful comment

@XiaoningLiu I was able to get around the audience issue and use the TokenCredential from the @azure/blob-storage SDK. I had to set the tokenAudience:

msRestNodeAuth.loginWithServicePrincipalSecretWithAuthResponse(
        clientId,
        secret,
        tenantId,
        { tokenAudience: 'https://storage.azure.com' }
      );

So I have a valid OAuth token from Azure AD using the service principal. My current error is this:

<?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:7555487a-a01e-0074-0c01-22276b000000
Time:2019-06-13T16:00:52.2708273Z</Message></Error>

Question - You've mentioned a direct incompatibility by just feeding objects between ms-rest-js and ms-rest-nodeauth. However, as long as that OAuth token is issued and valid, passing the token string directly as I'm doing should work right? I feel the above error is just setting the correct permissions / RBAC, etc. I've been googling around that and seen a few conflicting issues with RBAC and ACL. Any other pointers will be appreciated. I won't follow on this request any more as it seems this is permissions related if you agree. Thanks!

All 6 comments

@XiaoningLiu - Can you take a look at this issue?

I hope you can shed some light on this issue. I'm having the same problem. According to the documentation this should work. It noted that a TokenCredential (oauth) can be used. Each time the request goes out it is unsigned.

response: <?xml version="1.0" encoding="utf-8"?><Error><Code>AuthenticationFailed</Code><Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. </Message><AuthenticationErrorDetail>Audience validation failed. Audience did not match.</AuthenticationErrorDetail></Error>"

code:

 const result = await
    msRestNodeAuth.loginWithServicePrincipalSecretWithAuthResponse(
      clientId,
      secret,
      tenantId
    );
    const STORAGE_ACCOUNT_NAME = 'my_storage_account';

    const token = await result.credentials.getToken();

    const tokenCredential = new TokenCredential(token.accessToken);
    const pipeline = StorageURL.newPipeline(tokenCredential);
    const serviceURL = new ServiceURL(`https://${ STORAGE_ACCOUNT_NAME }.blob.core.windows.net`, pipeline);

    const containerName = 'mycontainer';
    const containerURL = ContainerURL.fromServiceURL(serviceURL, containerName);

    // List blobs
    let marker;

    do{
      const listBlobsResponse = await containerURL
        .listBlobFlatSegment(
          Aborter.none,
          marker
        );

      marker = listBlobsResponse.nextMarker;
      for(const blob of listBlobsResponse.segment.blobItems) {
        console.log(`Blob: ${ blob.name }`);
      }
    } while(marker);

Please refer to https://github.com/Azure/azure-sdk-for-js/issues/2934 about how to use node-auth with storage SDK to inter-op credentials between them.

Regarding to the error you mentioned, it means the token you got is not valid for storage auth. Please check how you get the token for storage.

@XiaoningLiu I was able to get around the audience issue and use the TokenCredential from the @azure/blob-storage SDK. I had to set the tokenAudience:

msRestNodeAuth.loginWithServicePrincipalSecretWithAuthResponse(
        clientId,
        secret,
        tenantId,
        { tokenAudience: 'https://storage.azure.com' }
      );

So I have a valid OAuth token from Azure AD using the service principal. My current error is this:

<?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:7555487a-a01e-0074-0c01-22276b000000
Time:2019-06-13T16:00:52.2708273Z</Message></Error>

Question - You've mentioned a direct incompatibility by just feeding objects between ms-rest-js and ms-rest-nodeauth. However, as long as that OAuth token is issued and valid, passing the token string directly as I'm doing should work right? I feel the above error is just setting the correct permissions / RBAC, etc. I've been googling around that and seen a few conflicting issues with RBAC and ACL. Any other pointers will be appreciated. I won't follow on this request any more as it seems this is permissions related if you agree. Thanks!

@ascholz81 Yes. Token Credential objects defined in ms-rest-nodeauth and @azure/storage-blob are both wrappers of OAuth token string. If the token string is valid, it will work for storage. So the left question is how to get a valid token string for storage. I think you are very close to success after resolved the audience issue.

Sorry I cannot provide much about debugging an invalid token, because I'm not good at it : (. At least, please carefully read through this official guideline how to access to storage with AD. Check the required roles have been assigned, and other checklist items.

https://docs.microsoft.com/en-us/rest/api/storageservices/authenticate-with-azure-active-directory

Thanks for working with Microsoft on GitHub! Tell us how you feel about your experience using the reactions on this comment.

Was this page helpful?
0 / 5 - 0 ratings