是否可以使用Azure Active Directory身份验证在本地调试Azure功能?

Mik*_*EEE 5 azure azure-active-directory azure-functions

我整天都在学习Azure Functions的工作方式。我已经在Azure Active Directory中注册了我的Azure功能,并且已经通过Azure门户中提供的Azure Active Directory对该应用程序进行了注册以确保安全。

我已将其部署到Azure,并且一切正常,要求我的Azure AD用户帐户,一旦登录,它就会按照预期显示我的HelloWorld Azure函数。

此外,我已经能够在本地调试Azure功能。但是,它在本地使用AuthorizationLevelmy HttpTriggerAttributeAuthorizationLevel.Anonymous)上配置的。

当然,在Azure中部署时会忽略此操作,但是现在在本地我已经失去了用户身份,因为它配置为匿名且未使用Azure Active Directory。

是否可以在本地部署的Azure功能上启用Azure Active Directory身份验证?

要在此处明确说明,我想像使用已部署的Azure Function一样在本地登录Azure Function(因此将重定向login.microsoftonline.com到登录名),但是我的本地Azure Function开发环境可以使用相同的身份。

感谢您提供的任何帮助!

Mik*_*EEE 6

好吧,再过几个(好吧,很多)小时后,我现在已经想出了一个解决方案。这适用于本地和部署的场景。我在这里发布了一个模板解决方案:

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

以下是概述整个过程的步骤:

  1. 在 https: function-name//.azurewebsites.net登录您的函数
  2. Chrome 中的 CTRL-SHIFT-C -> 应用程序 -> Cookies -> -> AppServiceAuthSession -> 复制值
  3. 打开local.settings.json并粘贴上一步AuthenticationToken设置中的值。
  4. 当你在那里时,粘贴第一步中的 URL AuthenticationBaseAddress
  5. 启动程序。
  6. 交叉手指。
  7. 享受魔法(希望如此)

这是主要事件:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:

  1. 一个HttpClient为每个调用创建。这违背了最佳实践。
  2. 示例代码基于@stuartleeks 的 EasyAuth 示例
  3. 该解决方案利用优秀的Refit项目来获取其数据。

为了完整起见,这里是剩余的感兴趣的类:

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. :(");
    }
}
Run Code Online (Sandbox Code Playgroud)