Adding Authentication to Your HTTP Triggered Azure Functions
Want to learn more about adding authentication to your HTTP-triggered Azure Functions? Check out this post to learn more about how to add authentication.
Join the DZone community and get the full member experience.
Join For FreeAzure Functions are great! HTTP triggered Azure Functions are an awesome tool, but there’s one downside — all HTTP triggered Azure Functions are publicly available. While this might be useful in a lot of scenarios, it’s also quite possible you don’t want ‘strangers’ hitting your public endpoints all the time.
One way you can solve this is by adding a small bit of authentication on your Azure Functions.
For HTTP-triggered functions, you can specify the level of authority one needs to have in order to execute it. There are five levels you can choose from. It’s Anonymous
, Function
, Admin
, System
, and User
. When using C#, you can specify the authorization level in the HttpTrigger
attribute, you can also specify this in the function.jsonfile
of course. If you want a Function to be accessed by anyone, the following piece of code will work, because the authorization is set to Anonymous
.
[FunctionName("Anonymous")]
public static HttpResponseMessage Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)]
HttpRequestMessage req,
ILogger logger)
{
// your code
return req.CreateResponse(HttpStatusCode.OK);
}
If you want to use any of the other levels, just change the AuthorizationLevel
enum to any of the other values corresponding to the level of access you want. I’ve created a sample project on GitHub containing several Azure Functions with different authorization levels, so you can test out the difference in the authorization levels yourself. Keep in mind, when running the Azure Functions locally, the authorization attribute is ignored, and you can call any function no matter which level is specified.
Whenever a different level of Anonymous
is used, the caller has to specify an additional parameter in the request to get authorized to use the Azure Function. Adding this additional parameter can be done in two different ways.
The first one is by adding a code parameter to the querystring
, which value contains the secret necessary for calling the Azure Function. When using this approach, a request can look like this.
Another approach is to add this secret value in the header of your request. If this is your preferred way, you can add a header called x-functions-key
, which value has to contain the secret code to access the Azure Function.
There are no real pros or cons to any of these two approaches — it quite depends on your solution needs and how you want to integrate these Functions.
Which Level Should I Choose?
Well, it depends.
The Anonymous
level is pretty straightforward, so I’ll skip this one.
The User
level is also fairly simple, as it’s not supported (yet). From what I understand, this level can and will be used in the future in order to support custom authorization mechanisms (EasyAuth). There’s an issue on GitHub, which tracks this feature.
The Function
level should be used if you want to give some other system (or user) access to this specific Azure Function. You will need to create a Function Key
, which the end-user/system will have to specify in the request they are making to the Azure Function. If this Function Key
is used for a different Azure Function, it won’t get accepted and the caller will receive a 401 Unauthorized.
The only ones left are the Admin and System levels. Both of which are fairly similar, they work with so-called Host Keys
. These keys work on all Azure Functions and are deployed on the same system (Function App). This is different from the earlier mentioned Function Keys
, which only work for one specific function.
The main difference between these two is that System only works with the _master
host key. The Admin level should also work with all of the other defined host keys. I’m writing the word should, because I couldn’t get this level to work with any of the other host keys. Both only appeared to be working with the defined _master
key. This might have been a glitch at the time, but it’s good to investigate once you get started with this.
How Do I Set up Those Keys?
Sadly, you can’t specify them via an ARM template (yet?). My guess is that this will never be possible because it’s something you want to manage yourself per environment. So, how to proceed? We'll head to the Azure Portal and check out the Azure Function you want to see or create keys for.
You can manage the keys for each Azure Function in the portal and even create new ones if you like.
I probably don’t have to mention this, but just to be on the safe side, you don’t want to distribute these keys to a client-side application. The reason for this is pretty obvious; it’s because the key will be sent in the request. Therefore, it’s not a secret anymore. Anyone can check out this request and see which key is sent to the Azure Function.
You only want to use these keys — both Function Keys
and Host Keys
— when making requests between server-side applications. This way your keys will never be exposed to the outside world and minimize the chance of a key getting compromised. If for some reason a key does become compromised, you can Renew or Revoke a key.
One Gotcha!
There’s one gotcha when creating an HTTP Triggered Function with the Adminauthorization
level. You can’t prefix these functions with the term Admin
. For example, when creating a function called AdministratorActionWhichDoesSomethingImportant
, you won’t be able to deploy and run it. You’ll receive an error there’s a routing conflict.
[21-8-2018 19:07:41] The following 1 functions are in error:
[21-8-2018 19:07:41] AdministratorActionWhichDoesSomethingImportant : The specified route conflicts with one or more built in routes.
Or when navigating to the Function in the portal you’ll get this error message popped up.
This is probably something you want to know in advance, before designing your complete API with Azure Functions.
Published at DZone with permission of Jan de Vries, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments