I have an Azure Function 2.x (Asp.net Core) and am authenticating with Azure AD. I'm trying to access the logged-in user's Claims after authentication. Previously using Azure Functions 1.x we would get the Claims using ClaimsPrincipal.Current, as seen in the code below:
using System.Net;
using System.Collections.Generic;
using System.Security.Claims;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
public static HttpResponseMessage Run(HttpRequestMessage req, out object document, TraceWriter log)
{
string name = ClaimsPrincipal.Current.FindFirst("name").Value;
log.Info($"name is {name}");
return req.CreateResponse(HttpStatusCode.OK, "Done");
}
Any guidance on how we access Claims in Azure Functions 2.x using .Net Core?
This feature is now supported in C# in Azure Functions 2.0. You can now add ClaimsPrincipal as a parameter to your HttpTrigger function's signature, or you can access it on the HttpRequest object via req.HttpContext.User.
Support should be coming soon to JavaScript, and eventually all languages should support this feature.
Let me just post a code example here, see where ClaimsPrincipal parameter is:
[FunctionName("MyFunctionName")]
public static HttpResponseMessage Run(
[HttpTrigger(
AuthorizationLevel.Anonymous,
"get", "post",
Route = "MyFunctionName")]HttpRequestMessage req,
ILogger log,
ClaimsPrincipal claimsPrincipal)
{
// My function code here...
}
Related
My goal is to secure my Azure Functions with Azure AD and call them from a WPF application.
I have an Azure Function with the following definition :
public IActionResult Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)]
HttpRequest req,
ILogger log,
ExecutionContext context,
ClaimsPrincipal claimsPrincipal)
I registered an Azure AD App and configured the settings for Native App Authentication :
I configured my app in the "Expose an API" bladd
I also added an API Permissions
I associated my app in my Azure Functions App in the Authentication / Authorization blade.
I am getting a token from Azure AD like this in a WPF app (using the Microsoft.Identity.Client library)
string applicationID = "***"; // My AppID Guid
PublicClientApp = PublicClientApplicationBuilder.Create(applicationID)
.WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient")
.Build();
var listScopes = new List<string>
{
//"user.read" - Removed based on #tony-yu recommendation
$"api://{applicationID}/MyScope"
};
var authResult = await PublicClientApp.AcquireTokenInteractive(listScopes)
.ExecuteAsync();
var myToken = authResult.AccessToken;
I can authenticate without any problem and I am successfully getting a token but whenever I call my function and I provide my token in the Authorization header (Authorization = Bearer ****), I get :
401 - You do not have permission to view this directory or page.
Here's how I call it (Postman) :
Here is the WWW-Authenticate header content when the call returns
When I check the token I got, it seems legit
Any idea what I am doing wrong?
The scope is not correct. As you want to access your function which is protected by ad, you need to use
var listScopes = new List<string>
{
"{applicationID}/.default"
};
instead.
user.read is the permission for Microsoft Graph API.
So I finally made it work thanks to this SO article here by ambrose-leung
I am building an ASP NET Core web application that will perform a delete operation for a user on a remote datastore. Currently, I have a frontend web app that communicates with Azure Functions to delete a user. I have a concern with security. How can I make sure the user is the logged-in user? Currently, in my ASP Net Core Web App, I have the user authenticate with AAD using Microsoft as an Identity Provider. From a client-side, the user is verified and taken care of. However, my app calls the Azure Functions endpoints. Is there an extra level of security that I could add. I only want to give my web app (registered in Azure) the ability to call the endpoints.
There are two main ways to authenticate your users. One is to use the App Services authentication options: https://learn.microsoft.com/en-us/azure/app-service/configure-authentication-provider-aad. This is by far the easier method.
If you need more control over things than what is available in the service, then you can implement validation within the Function itself as Thiago mentioned. Ben Morris did a fairly detailed post on how to implement your own OAUTH provider inside your Function App with C#: https://www.ben-morris.com/custom-token-authentication-in-azure-functions-using-bindings/ If you can take care of the validation in the Function's DI container, validation inside a specific function is fairly clean as seen in the post:
public class ExampleHttpFunction
{
private readonly IAccessTokenProvider _tokenProvider;
public ExampleHttpFunction(IAccessTokenProvider tokenProvider)
{
_tokenProvider = tokenProvider;
}
[FunctionName("ExampleHttpFunction")]
public IActionResult Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "example")] HttpRequest req, ILogger log)
{
var result = _tokenProvider.ValidateToken(req);
if (result.Status == AccessTokenStatus.Valid)
{
log.LogInformation($"Request received for {result.Principal.Identity.Name}.");
return new OkResult();
}
else
{
return new UnauthorizedResult();
}
}
}
We are planning to build a web application, and I was hoping someone could help us to decide whether to use Azure App Service or Azure Function for providing rest API to the client side.
Our requirements are as follows.
Authentication and authorization
CRUD on Azure SQL and Cosmos DB
Multi region
100,000,000 API calls per month
At first, we were going to build the backend using Azure App Service. But after studying pros and cons on Azure Functions, Azure Functions became more appealing to us.
So is it even a good idea to build a web application that depends on Azure Functions as a REST API provider?
Does anyone have an experience building, managing and scaling up and out Azure Functions as a REST API provider?
Is it even a good idea to build a web application that depends on Azure Functions as a REST API provider?
It seems you are planning to have REST API using Web Service or Azure Function. Your decision is perfect I would say. For Azure Function its not mandatory to have web service for that. Azure function would be best option for you. You can implement all the feature that Web API provides. So if your target is only develop API then you can start with Azure Function with no other alternative. Its outstanding actually!
Does anyone have an experience building, managing and scaling up and out Azure Functions as a REST API provider?
I am working with Azure Function for our AI Base Bot with LUIS integration. From my understanding it's a very easily maintainable, fastest response time, you can build it from anywhere. So you can undoubtedly go with Azure function.
Why Choose Azure Function:
It's stateless, need not any server to run
Full REST, can call from anywhere any Region
Can develop both Azure Portal and local Visual Studio
Cost-effective, you can pay only how much you use.
Multiple language support
Easy Authorization and Authentication functionality
No limit of calling as per your consumption plan
Do A Lot With Azure Function:
You can develop a robust API service with Azure functions. It has many outstanding features. Please check Check here
Authorization and Authentication:
You can simply integrate your authorization and authentication on your function App. Even you can implement it on each function separately or on a full application. It supports most of the popular authentication provider for example:
Azure Active Directory
Microsoft Identity
Goggle
Facebook
Twitter auth
See how can you implement authentication:
Step:1
Step:2
Rest Function Code Sample:
Here I am giving you a simple code snippet to start with: though it's on Azure Table Storage, but help you to develop azure function and CRUD concept.
Your Sample Class:
public class YourSampleClass
{
public string PartitionKey { get; set; }
public string RowKey { get; set; }
}
Table Storage Class:
public class TableStorageClass
{
public TableStorageClass()
{
}
public TableStorageClass(DynamicTableEntity entity)
{
PartitionKey = entity.PartitionKey;
RowKey = entity.RowKey;
}
public string PartitionKey { get; set; }
public string RowKey { get; set; }
}
Azure Function V2 Example:
public static class FunctionReadFromTableStorage
{
[FunctionName("FunctionReadFromTableStorage")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
//Read Request Body
var content = await new StreamReader(req.Body).ReadToEndAsync();
//Extract Request Body and Parse To Class
YourSampleClass objYourSampleClass = JsonConvert.DeserializeObject<YourSampleClass>(content);
// Validate param because PartitionKey and RowKey is required to read from Table storage In this case , so I am checking here.
dynamic validationMessage;
if (string.IsNullOrEmpty(objYourSampleClass.PartitionKey))
{
validationMessage = new OkObjectResult("PartitionKey is required!");
return (IActionResult)validationMessage;
}
if (string.IsNullOrEmpty(objYourSampleClass.RowKey))
{
validationMessage = new OkObjectResult("RowKey is required!");
return (IActionResult)validationMessage;
}
// Table Storage operation with credentials
var client = new CloudTableClient(new Uri("https://YourStorageURL.table.core.windows.net/"),
new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials("YourStorageName", "xtaguZokAWbfYG4QDkBjT+YourStorageKey+T/kId/Ng+cl3TfYHtg=="));
var table = client.GetTableReference("YourTableName");
//Query filter
var query = new TableQuery()
{
FilterString = string.Format("PartitionKey eq '{0}' and RowKey eq '{1}'", objYourSampleClass.PartitionKey, objYourSampleClass.RowKey)
};
//Request for storage query with query filter
var continuationToken = new TableContinuationToken();
var storageTableQueryResults = new List<TableStorageClass>();
foreach (var entity in table.ExecuteQuerySegmentedAsync(query, continuationToken).GetAwaiter().GetResult().Results)
{
var request = new TableStorageClass(entity);
storageTableQueryResults.Add(request);
}
//As we have to return IAction Type So converting to IAction Class Using OkObjectResult We Even Can Use OkResult
var result = new OkObjectResult(storageTableQueryResults);
return (IActionResult)result;
}
}
Point To Remember:
In case of Azure Portal execution just get rid of FunctionReadFromTableStorage class
You Need following reference to execute above code
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Microsoft.WindowsAzure.Storage.Table;
using System.Collections.Generic;
Postman Request Pattern:
Function Invoke Sample:
{
"PartitionKey": "Your Param According to Table Storage Design" ,
"RowKey": "Your Param According to Table Storage Design",
"Directory": "Your Param According to Table Storage Design"
}
See The Screen Shot:
Post Man Response:
Response is subject to my own table design
[
{
"partitionKey": "Microsoft SharePoint Server",
"rowKey": "2016"
}
]
See The Screen Shot Below:
Note: For CosmosDb Integration you could check here. Azure SQL with Function take a look here.
I've set up my Azure Functions 2 in the manner described in this post https://blogs.msdn.microsoft.com/stuartleeks/2018/02/19/azure-functions-and-app-service-authentication/
I can call the /.auth/login/google endpoint with the Google token and get back the easy auth token.
And I can call the /.auth/me endpoint and get back my profile info.
But in my code, the Thread.CurrentPrincipal.Identity is null. I can't seem to find any solution to this. I have verified my request has the x-zumo-auth header set to the easy auth token retrieved from the login endpoint. And of course the function is set to anonymous.
I hope I'm missing something simple. Thanks for your help.
Since November 28th 2018, this feature is now in preview. This capability is only available to the Functions 2.x runtime. It is also currently only available for .NET languages.
The ClaimsPrincipal is available as part of the request context as
shown in the following example:
using System.Net;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
public static IActionResult Run(HttpRequest req, ILogger log)
{
ClaimsPrincipal identities = req.HttpContext.User;
// ...
return new OkResult();
}
Alternatively, the ClaimsPrincipal can simply be included as an
additional parameter in the function signature:
using System.Net;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
using Newtonsoft.Json.Linq;
public static void Run(JObject input, ClaimsPrincipal principal, ILogger log)
{
// ...
return;
}
Reference: https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook#working-with-client-identities
Found the answer but still I'm surprised there is such a lack of clarity.
https://learn.microsoft.com/en-us/azure/app-service/app-service-authentication-overview
For Azure Functions, ClaimsPrincipal.Current is not hydrated for .NET code, but you can still find the user claims in the request headers.
But there's countless examples I'm seeing where people reference that in Azure Functions as if it should be hydrated.
I am indeed finding the claims as expected in the headers and will work with that, but I feel like there's still something that I'm missing...
I've set up my Azure Function and I can see that there are options to support Azure Active Directory for authentication, which looks great. In a previous project I have used .NET Core to host a WebAPI and subsequently used Authorisation Policies (https://learn.microsoft.com/en-us/aspnet/core/security/authorization/) to provide fine grained claims based authorisation in my API. I cannot seem to find an equivalent mechanism in an Azure Function.
Can anyone tell me if there is a way to do this sort of thing in an Azure Function?
There is not currently built-in support for fine-grained authorization. This would make a great suggestion item for the Functions UserVoice.
You could always write authorization logic as a part of your function, although a built-in feature would certainly be better. The below code snippet (C#) does an authentication check in code and prints a list of claims. You could modify it to require specific claims:
using System.Net;
using System.Threading;
using System.Security.Claims;
public static void Run(HttpRequestMessage req, TraceWriter log)
{
if (!Thread.CurrentPrincipal.Identity.IsAuthenticated)
{
log.Info("Not authenticated");
return req.CreateResponse(HttpStatusCode.Unauthorized);
}
ClaimsIdentity identity = (Thread.CurrentPrincipal as ClaimsPrincipal)?.Identity as ClaimsIdentity;
if (identity != null)
{
foreach (var claim in identity.Claims)
{
log.Info($"{claim.Type} = {claim.Value}");
}
}
// Rest of your function...
return req.CreateResponse(HttpStatusCode.OK);
}
Note that in non-.NET languages, you would want to inspect the headers for claims information. You could also combine this with calls to the /.auth/me endpoint and provider graph endpoints.