I am trying to set up an Azure Function which will serve files from Blob Storage. I want to be able to use Microsoft Entra ID (formerly Azure AD) authentication with Attribute-Based Access Controls (ABAC) to control access to the blobs based on a combination of group membership and blob index tags. That works fine when trying to access the blobs through the Storage REST API, but I would like to be able to simply have a URL that will trigger authentication if needed and allow the user to view the blob in a browser (the blobs will be images).
The general approach is basically that described here: Access a blob file via URI over a web browser using new AAD based access control. However, the solution in that post is based on an earlier version of OAuth / AAD, and no longer seems to apply to OAuth 2.0.
I have the Azure Function set up with Entra authentication, and that works - when I hit my function URL, I go throught the auth flow, and get a token which I can access in my function code like so:
var accessToken = req.Headers.FirstOrDefault(p => p.Key.Equals("x-ms-token-aad-access-token", StringComparison.OrdinalIgnoreCase));
However, when I present this token to the Storage API, I get the following error:
<Error>
<Code>InvalidAuthenticationInfo</Code>
<Message>Server failed to authenticate the request. Please refer to the information in the www-authenticate header. RequestId:20312ea0-c01e-003d-49f4-28d43b000000 Time:2023-12-07T10:04:34.9679103Z</Message>
<AuthenticationErrorDetail>Signature validation failed. Signature verification failed.</AuthenticationErrorDetail>
</Error>
The www-authenticate header on the response contains:
Bearer authorization_uri=https://login.microsoftonline.com/<my app ID>/oauth2/authorize resource_id=https://storage.azure.com
But I'm not sure what to do with this information.
I have configured the Azure Storage user_impersonation permission on my App Registration.
I have configured the following allowed token audiences in the settings for the apps identity provider:
api://<my app id>,
https://storage.azure.com/.default
https://storage.azure.com
https://storage.azure.com/user_impersonation
https://stasepaimagespoc.blob.core.windows.net/user_impersonation
I have attempted to specify additionalLoginParams in the app's authsettings through Azure Resource Manager as described in the post I referenced earlier, but this returns the error "Cannot execute the request for site because the site is running on auth version v2", and I can't see anything equivalent in authsettingsV2.
I have decoded the token using JWT.IO, and I see that the "aud" value is "00000003-0000-0000-c000-000000000000", which according to a post I found on "Troubleshooting Signature Validation Errors" (link removed as SO thinks it's spam) indicates this this is a Graph token which cannot be validated by anything other than Graph. That post seems to say that I need to change the scope parameter for the token request, but I don't know how to do that.
Does anybody have any suggestions?
Lol - I've been banging my head against this for two days, and then half and hour after posting the question here, I find the solution... Thanks to Setting additionalLoginParams with auth v2 which provided the key information.
What I needed to do to make this work was to add a scope specification to the login request, and the way you do that under oath2 is by adding a loginParameters
element under properties.identityProviders.login
for authsettingsV2 in Azure Resource Explorer, like so:
"login": {
"loginParameters": [
"scope=openid https://storage.azure.com/.default"
],
"disableWWWAuthenticate": false
}