skip to Main Content

I have an Azure Static Web App that is configured with AAD, aka Entra ID, authentication. I also have an Azure Function App that I have deployed separately and then linked to the Static Web App as a backend. To be extra clear, this Function App is a linked backend (BYOF), and not a managed function.

I want to be able to call the Microsoft Graph API from the Function App, using delegated permissions from the authentication that is done in the Static Web App, and retrieve user information such as name, surname, email, photo etc. for users based on id.

I have added the delegated permission User.ReadBasic.All to my App Registration for my Static Web App (same one that is used to configure auth).

What else needs to be done to be able to authenticate the Function App against the Microsoft Graph API on behalf of the user of my Static web App?

2

Answers


  1. Chosen as BEST ANSWER

    I found the other answer to be a little confusing and misleading, so I thought I'd post my own:

    It is possible to set up the on-behalf-of flow with Azure Static Web App and Linked Backend (BYOF Function App), but not through the built-in authentication (the one that you set up through the Static Web App config file). This must be done "manually" by using the Microsoft Authentication Library (MSAL).

    Microsoft provides a tutorial on how to do this, which can be found in their GitHub repo.

    However, I decided to take another path and assign application permissions to my app registration instead, which - unlike delegated permissions - requires admin consent.

    I hope this post can be helpful to someone facing the same kind of problem.


  2. As you are using BYOF, The Function code will work separately and the authentication you are doing in Azure Static Web app will not work. And as Azure Functions cannot run interactive login inside the App, You cannot use User specific flows like Implicit flow or Auth code flow wherever User interaction via Browser login is required.

    Here, You need to create one Azure Functions with Client Credentials Flow using Azure service principal- Client Id, Client Secret and Tenant Id like below.

    Reference here.

    My Function1.cs:-

    using Azure.Core;
    using Azure.Identity;
    using Newtonsoft.Json;
    using System;
    using System.Net.Http;
    using System.Threading.Tasks;
    using Azure.Core;
    using Azure.Identity;
    using Newtonsoft.Json;
    using System;
    using System.Net.Http;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Extensions.Http;
    using Microsoft.Extensions.Logging;
    using System.Net.Http.Json;
    
    namespace FunctionApp1
    {
        public static class Function1
        {
            [FunctionName("Function1")]
            public static async Task<IActionResult> Run(
                [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
                ILogger log)
            {
                log.LogInformation("C# HTTP trigger function processed a request.");
    
                var token = await GetAccessToken("Tenant-Id", "Client-Id", "Client-Secret");
                var results = await GetResults(token);
    
                return new OkObjectResult(results);
            }
    
            private static async Task<string> GetAccessToken(string tenantId, string clientId, string clientKey)
            {
                var credentials = new ClientSecretCredential(tenantId, clientId, clientKey);
                var result = await credentials.GetTokenAsync(new TokenRequestContext(new[] { "https://graph.microsoft.com/.default"
    }), default);
                return result.Token;
            }
    
            private static async Task<string> GetResults(string token)
            {
                var httpClient = new HttpClient
                {
                    BaseAddress = new Uri("https://graph.microsoft.com/v1.0/")
                };
    
                string URI = $"users/a8f97275-2685-41ce-a61d-dc550cd090f8";
    
                httpClient.DefaultRequestHeaders.Remove("Authorization");
                httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
                HttpResponseMessage response = await httpClient.GetAsync(URI);
    
                var HttpsResponse = await response.Content.ReadAsStringAsync();
                //var JSONObject = JsonConvert.DeserializeObject<object>(HttpsResponse);
    
                //return response.StatusCode.ToString();
                return HttpsResponse;
            }
        }
    }
    

    Output:-

    enter image description here

    enter image description here

    Now, Add this Function in your Azure static web app and call it along with the static web app URL as mentioned in my SO answer.

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search