Is it Possible to Debug Azure Functions Locally with Azure Active Directory Authentication?

后端 未结 2 1303
粉色の甜心
粉色の甜心 2020-12-15 13:34

I have been spending the day learning how Azure Functions work. I have gotten my Azure Function registered with my Azure Active Directory, and have registered this applicat

相关标签:
2条回答
  • 2020-12-15 14:02

    Alright after a few more (OK, a LOT) hours, I have figured out a solution for now. This works in both local and deployed scenarios. I have posted a template solution here:

    https://github.com/Mike-EEE/Stash/tree/master/AzureV2Authentication/AzureV2Authentication

    Here are the steps that outline the overall process:

    1. Sign into your function at https://function-name.azurewebsites.net
    2. CTRL-SHIFT-C in Chrome -> Application -> Cookies -> -> AppServiceAuthSession -> Copy Value
    3. Open local.settings.json and paste value from previous step in AuthenticationToken setting.
    4. While you're there, paste in the URL from first step in AuthenticationBaseAddress
    5. Launch application.
    6. Cross fingers.
    7. Enjoy magic (Hopefully.)

    Here is the main event:

    public static class AuthenticationExtensions
    {
        public static Authentication Authenticate(this HttpRequest @this)
        {
            var handler = new HttpClientHandler();
            var client = new HttpClient(handler) // Will want to make this a singleton.  Do not use in production environment.
            {
                BaseAddress = new Uri(Environment.GetEnvironmentVariable("AuthenticationBaseAddress") ?? new Uri(@this.GetDisplayUrl()).GetLeftPart(UriPartial.Authority))
            };
            handler.CookieContainer.Add(client.BaseAddress, new Cookie("AppServiceAuthSession", @this.Cookies["AppServiceAuthSession"] ?? Environment.GetEnvironmentVariable("AuthenticationToken")));
    
            var service = RestService.For<IAuthentication>(client);
    
            var result = service.GetCurrentAuthentication().Result.SingleOrDefault();
            return result;
        }
    }
    

    Note that:

    1. An HttpClient is created for each call. This is against best practices.
    2. Sample code is based on EasyAuth sample by @stuartleeks
    3. This solution makes use of the excellent Refit project to get its data.

    Here are the remaining classes of interest, for the sake of completeness:

    public class Authentication // structure based on sample here: https://cgillum.tech/2016/03/07/app-service-token-store/
    {
        [JsonProperty("access_token", NullValueHandling = NullValueHandling.Ignore)]
        public string AccessToken { get; set; }
        [JsonProperty("provider_name", NullValueHandling = NullValueHandling.Ignore)]
        public string ProviderName { get; set; }
        [JsonProperty("user_id", NullValueHandling = NullValueHandling.Ignore)]
        public string UserId { get; set; }
        [JsonProperty("user_claims", NullValueHandling = NullValueHandling.Ignore)]
        public AuthenticationClaim[] UserClaims { get; set; }
        [JsonProperty("access_token_secret", NullValueHandling = NullValueHandling.Ignore)]
        public string AccessTokenSecret { get; set; }
        [JsonProperty("authentication_token", NullValueHandling = NullValueHandling.Ignore)]
        public string AuthenticationToken { get; set; }
        [JsonProperty("expires_on", NullValueHandling = NullValueHandling.Ignore)]
        public string ExpiresOn { get; set; }
        [JsonProperty("id_token", NullValueHandling = NullValueHandling.Ignore)]
        public string IdToken { get; set; }
        [JsonProperty("refresh_token", NullValueHandling = NullValueHandling.Ignore)]
        public string RefreshToken { get; set; }
    }
    public class AuthenticationClaim
    {
        [JsonProperty("typ")]
        public string Type { get; set; }
        [JsonProperty("val")]
        public string Value { get; set; }
    }
    interface IAuthentication
    {
        [Get("/.auth/me")]
        Task<Authentication[]> GetCurrentAuthentication();
    }
    public static class Function1
    {
        [FunctionName("Function1")]
        public static IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequest req, TraceWriter log)
        {
            log.Info("C# HTTP trigger function processed a request.");
    
            var authentication = req.Authenticate();
    
            return authentication != null
                ? (ActionResult)new OkObjectResult($"Hello, {authentication.UserId}")
                : new BadRequestObjectResult("Authentication not found. :(");
        }
    }
    
    0 讨论(0)
  • 2020-12-15 14:24

    Here is another alternative if you are developing a SPA with JWT tokens that uses Azure-AD or Azure B2C via Easy Auth.

    0 讨论(0)
提交回复
热议问题