I have created a new Function App, enabled App Service Authentication / Authorization for it ("Use Authentication / Authorization to protect your application and work with per-user data") and disabled non-authenticated requests.
Everything seems to be working correctly so far. If I try to request my HttpTrigger
ed function, it requires me to log in first; once I'm logged in, all requests are processed as they should be. So there is no problem with "protect your application" part.
However, I'm totally stuck with the "work with per-user data" part. My Azure Function is invoked as
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
And there is nothing related to authentication in HttpRequestMessage
. (AuthorizationLevel.Anonymous seems to control the entirely different thing - namely, if the function could be called by anyone or only by those who have a fixed API key).
How do I get the identity of authenticated user who called the function?
Logically, AuthorizationLevel.Anonymous will not give you a current claims principal.
Unfortunately, just changing to AuthorizationLevel.Function doesn't help either: For me I am finding that ClaimsPrincipal.Current is null, even after authenticating successfully via Azure Active Directory B2C.
Finally, I tried AuthorizationLevel.User, but that isn't currently supported by azure functions see here
I believe you need to follow the steps as per the accepted answer on this SO question (I'm in process of trying it now ...)
It seems that one can get current user name from global state
System.Security.Claims.ClaimsPrincipal.Current.Identity.Name
(I didn't know that when I originally posted this question). However, it is unclear if this is a reliable or recommended method of getting logged in user info.Example:
First class integration with App Service EasyAuth is something that isn't in place yet, but we're tracking in our repo here. We're looking at this now and will likely have some improvements in this area very soon.
As you discovered, you can enable EasyAuth and it will require login, and will flow the authenticated principal through, allowing you to access it via standard .NET APIs like ClaimsPrincipal.Current, etc. However the problem is that you had to mark your method with auth level Anonymous which isn't what you want, and requires you to reject unauthenticated requests in your method (see notes in issue referenced above).
We'll iron all these issues out soon in an upcoming release.
Copied from my issue here, which was intended to find how to debug locally with an Azure Active Directory authenticated user.
https://stackoverflow.com/a/49402152/3602057
This will work with any provider that is configured on Azure with your Azure Function, and will work while for both local debugging and deployed scenarios.
Alright after a few more (OK, a LOT) hours, I have figured out a solution for now. This works in both local and deployed scenarios. I have posted a template solution here:
https://github.com/Mike-EEE/Stash/tree/master/AzureV2Authentication/AzureV2Authentication
Here are the steps that outline the overall process:
function-name
.azurewebsites.netlocal.settings.json
and paste value from previous step inAuthenticationToken
setting.AuthenticationBaseAddress
Here is the main event:
Note that:
HttpClient
is created for each call. This is against best practices.Here are the remaining classes of interest, for the sake of completeness:
Using the Azure Function runtime v2.0.12309, you can retrieve the authenticated user information from the ClaimsPrincipal instance injected in the
Run
method: