Pages

Wednesday, June 21, 2017

Calling Azure functions from C# with security enabled

Azure functions allow us to run server-less code. We will see how, and in the interest of this sample we will simulate the problem of having to run some code when a payment is done, the code to do it will be on azure and the call would come from our C# payment app.
So to ensure we don't get unauthorized calls, we will activate security on our Azure function and I will show you how to make a secure call and review the azure logs for those calls. So lets begin.

Part 1 - Azure function

In order to create our azure function lets head to:
portal.azure.com
and enter your credentials, if you dont have an azure account, you can get a trial account for free.

Once inside the portal click on the new button '+' then on 'Compute' and on the FuctionApp option.



Then we will set the name of our new function as  ‘licensefunctions’ and click on ‘Create’ (If the name is not available just choose one you see fit)



Azure will take a moment to complete the request. And then we will get the 'completed' message, and we will see our newly created function listed on the ’all resources’ tab of the Azure Panel:


Click on the function name to open it.
Then click on the ‘+’ button and select the ’Custom function’ option to create a function with a selected name.


Choose the ‘Generic WebHook CSharp’’ So we can code our function on C#.


Then on the bottom of the page select your function's name, in this case we choose ‘gotpayment’, and click on create.


As a result we get a function with default functionality, This function receives a Json object with data to process. In this case we will receive the client's name and email.

Then after some processing (maybe storing the data on a database or azure table for another App to pick it or verifying some bank account. That is out of the scope of this post, maybe on a following post we will make a complete sample)
We will respond to the caller indicating his payment has been received and a license would be sent. So this is how the final code of our function:



We used dynamic for the object reveived so we check to see if the expected fields are available and then we return our answer, pretty straight forward, there would be some processing if we need to (again, out of the scope of this post, because we will focus on the security aspect).
Now lets click on the ‘Get function URL’ option to get an address to call our service.

Lets delete the code from the query as we will send it in a better way. so we get the url:
https://licensefunctions.azurewebsites.net/api/gotpayment

The basic azure security is based on those codes, like the one we see in the url, So where are those Id codes managed?
Just click on the ‘manage’ option below our ‘gotpayment’ function and we will see the function keys. We can have more than one, and we can Revoke, or renew any key if we believe it has been compromised. To see the Key click on the ‘click to show’ link.



And we get our current key, take a note of it, as we will need it for our C# code.
Save your function, and its now ready and running, let leave it alone for a second,

Part 2 - C# app

To show you how to interact with our azure function we will write a C# console app, this code could be very well inside any other type of app, we will do it like this for the sake of brevity.
So lets create a C# console App and name it ‘MyPaymentApp’:


 Then add the newtonsoft.Json package to make our life easier when handling json objects:

And add the following using to our app:


Now we will create a function to call our Azure URL with the data needed:
  • First we set the azure function URL.
  • Then we create our json object with the name and email to send.
  • We add our json object to the content to send.
  • Then we send those and wait for the answer.
  • Once we get the answer we deserialize it and return the message we got.
So far we have this:

Oh, But lets not forget the security! we need to send the code in the call to ensure azure will process our request, otherwise we will get an error message back.

There are two ways to do it, one is on the URL itself:


But the second one, and preferred by me, is to  add it in the headers of the call, we can do this by including the header:
x-functions-key
In the http call ,with a value of the id code.
So our final code looks like this:





Let run it to see if it works:


We can see that the security code was accepted in the header and we get the expected answer. We can actually make an azure function that would trigger and send that email, but that will be part of another post. ;)

There is one more thing I want to show you, Lets see the Azure Logs, to see if we logged our API call.

Back to our Azure functions portal if we click on the ‘Monitor’ Option under our 'gotpayment' function we can see the calls made and the log saved.



And that, my friend , it’s all!

10 comments:

  1. Nice post, thank you, was struggling a bit on how to get the address for the HttpClient to call the Azure Function, this pointed me into the right direction

    ReplyDelete
  2. Thanks for this very helpful article

    ReplyDelete
  3. This post was really helpful got my azure function working thro ugh this code but i am getting one error Unexpected character encountered while parsing value: H. Path '', line 0, position 0.
    instead of executing it successfully

    ReplyDelete
    Replies
    1. If you could share part of your code I might be able to see if there is anything missing.

      Delete
  4. This comment has been removed by the author.

    ReplyDelete
  5. This comment has been removed by the author.

    ReplyDelete



  6. [FunctionName("Function1")]
    public async Task Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
    ILogger log,ExecutionContext context)
    {
    log.LogInformation("C# HTTP trigger function processed a request.");

    // string name = req.Query["employeeId"];

    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    log.LogInformation(requestBody);
    log.LogInformation("azure function called..");
    dynamic data = JsonConvert.DeserializeObject(requestBody);
    string ClientId = data?.ClientId;
    log.LogInformation($"azure function called..{ClientId}");
    // string ClientId = "";
    // ClientId = "109";//individual
    GeneratePdf generatePdf = new GeneratePdf(log,context);
    await generatePdf.Savepdf(Convert.ToInt32(ClientId));
    string responseMessage = string.IsNullOrEmpty(ClientId)
    ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
    : $"Hello, {ClientId}. This HTTP triggered function executed successfully.";

    return new OkObjectResult(responseMessage);
    }
    }
    this is the azure function code

    ReplyDelete
  7. static string securityCode = "";

    static void Main(string[] args)
    {
    //A payment has been received ! So lets register it in our azure function
    //remember this is sample data, you would call this with the real paying client info
    System.Console.WriteLine("\n\nCalling Generate Pdf Azure function...");
    int clientId = ;
    string result = RegisterPaymentAsync(clientId, securityCode);
    System.Console.WriteLine("\n\nRegistration answer: {0}", result);
    System.Console.WriteLine("\n\nPress enter to exit...");
    System.Console.ReadLine();
    }

    static string RegisterPaymentAsync(int clientId, string securityCode)
    {
    string result = string.Empty;

    var askForlicenseURL = "https://eag-dev-generatepdf-2.azurewebsites.net/api/Function1";
    var myObject = (dynamic)new JObject();
    myObject.ClientId = clientId;
    // myObject.email = email;

    var content = new StringContent(myObject.ToString(), Encoding.UTF8, "application/json");

    using (HttpClient client = new HttpClient())
    {
    client.DefaultRequestHeaders.Add("x-functions-key", securityCode);
    using (HttpResponseMessage response = client.PostAsync(askForlicenseURL, content).Result)
    using (HttpContent respContent = response.Content)
    {
    // ... Read the response as a string.
    var tr = respContent.ReadAsStringAsync().Result;
    // ... deserialize the response, we know it has a 'result' field
    dynamic azureResponse = JsonConvert.DeserializeObject(tr);
    // ... read the data we want
    result = azureResponse.result;
    }
    }
    return result;
    }

    ReplyDelete
  8. this is the console app (consumer app code)

    ReplyDelete