What is whitelisting
Whitelisting enables you to restrict access and allow certain calls to the Process. In Frends, you can restrict access to Processes that use API and HTTP Trigger by configuring the Authorization header which the Trigger checks when a call comes in. In some cases, these are not enough and you would need additional restrictions to ensure that the call comes from the correct source. These cases are the reason for whitelisting. Unfortunately, at the moment there are no ready-made solutions in Frends that could implement this feature. The only way to do the whitelisting is inside the Process itself.
IP whitelist
IP whitelist can be implemented inside the Process by checking the IP address of the caller. This can be done by using the #trigger.data.httpClientIp
reference. This reference will get the IP address from the incoming message and you can then check if the IP is the one you are going to allow. The checking can be done by creating a list of allowed IP addresses and checking if the IP address is inside that list. The best practice for this is to use Environment Variables to store the allowed IP addresses. You can do this by creating a new Environment Variable Group with a List-typed variable.
In the process, you can use the Environment Variable reference #env
to reference the specific variable and check if the incoming IP is inside that list. However, the Frends Environment Variable list is an array of objects: System.Object[]
which doesn't have the Contains()
method. Because of this, you need to convert the array into a System.Generic.Collections.List. The best method is casting the array into an object[]
array and then using the ToList()
method to convert the array into a List. Afterward, you can use the Contains()
method to check whether the incoming IP is inside the list.
Complete code: ((object[])#env.Security.AllowedIPAddresses).ToList().Contains(#trigger.data.httpClientIp)
After the Decision Element, you can either throw e.g. Unauthorized HTTP Response, or continue with the other parts of the Process.
Basic Auth in Process
Basic authentication in Frends HTTP Trigger authenticates request users either against Active Directory (AD) or local machine users. This will depend on the Agent user. In case the Agent uses a local account, users are authenticated against the local machine users. If the Agent uses an AD user account, users are authenticated against the AD users.
Basic authentication is not supported when using Frends PaaS Agents. However, you can build the Basic Authentication inside the Process itself. When you're building the Basic authentication inside the Process you have to set the Authorization parameter in the HTTP Trigger to None. This means that Frends does not try to handle the authorization in the Trigger and lets the request continue to the main part of the Process.
The most simple way to do Basic authentication inside the Process is to use Environment variables. Because we know that Basic authentication is formatted from username and password separated by a colon (username:password), we can store user credentials to Environment Variables in that same format. We can create a new Environment Variable Group and in that group, we can set up a List typed variable where we can store all credentials we want to allow to send requests to the Process.
Example
First, we can check that the request has an authorization header and that the correct value of that header is the Basic authentication. This can be done by checking first if the #trigger.data.httpAuthorization
is null or empty: !string.IsNullOrEmpty(#trigger.data.httpHeaders.Authorization)
. The second thing we want to know is if the authorization header uses the correct authentication method. This can be checked if the value starts with "Basic": #trigger.data.httpHeaders.Authorization.ToLower().StartsWith("basic")
. In this example the ToLower()
method is used to make sure that case sensitivity doesn't matter.
Complete code:
!string.IsNullOrEmpty(#trigger.data.httpHeaders.Authorization) && #trigger.data.httpHeaders.Authorization.ToLower().StartsWith("basic")
This will filter requests which don't have the correct headers. Next, we can do the actual Basic authentication check. We know that the Basic authentication header value comes in a Base64 formatted string leading by the word "Basic ": Basic <Base64String>. For us to extract the credentials from the string, we need to make some modifications and conversions to it. First, we need to separate the "Basic " and the Base64 format strings from each other. This can be done with code:
var authPart = #trigger.data.httpHeaders.Authorization.Replace("Basic", string.Empty).TrimStart();
.
Here we use the Replace()
method to replace the "Basic" with an empty string. Next, we Trim the leading white space from the Base64 formatted string.
The next step is to convert the Base64 string into bytes. This can also be done with a code: var credsBytes = Convert.FromBase64String(authPart);
. After that, we can get the string from the bytes by using System.Text.Encoding namespace to convert the bytes into a string: var creds = System.Text.Encoding.ASCII.GetString(credsBytes);
. Note that you need to use specific encoding with this method if the password can include special characters. After this, we can return the converted credentials in plain text.
Complete code for this:
var authPart = #trigger.data.httpHeaders.Authorization.Replace("Basic", string.Empty).TrimStart();
var credsBytes = Convert.FromBase64String(authPart);
var creds = System.Text.Encoding.ASCII.GetString(credsBytes);
return creds;
This allows us to check if our Environment Variables have those credentials stored. This can be done by casting the Environment Variable into an object array and converting it to list type after which we can use the Contains()
method to check if the credentials are inside.
Complete code: ((object[])#env.Security.AllowedUsers).ToList().Contains(#var.credentials);
This is one way to check user credentials inside a request using Basic Authentication.
Note that Frends is not the correct place to store user credentials and this demo was using them to demonstrate how to handle Basic authentication. A more secure way is to use some sort of database or AD.
The next article is the beginning of the Architecture course Introduction to Key Concepts in Frends Architecture