Azure active directory 在WebApi中验证Azure广告令牌

Azure active directory 在WebApi中验证Azure广告令牌,azure-active-directory,Azure Active Directory,我们正在构建一个webAPI服务,客户将使用AAD令牌访问该服务。因此,该服务需要对令牌进行身份验证,以确保其有效。 这是一个多租户场景 我查阅了AAD文档,没有什么问题。如果有人能帮助回答,我们将不胜感激 1) 根据我的理解,该服务将从AAD下载公共签名令牌并缓存它们。这些用于验证令牌,对吗 2) 刷新缓存签名令牌的建议间隔是多久?此外,如果AAD在刷新周期内旋转键,建议按需刷新 3) 根据我在中找到的AAD示例代码 由于计算机不信任AAD根证书,因此启用证书验证不起作用,这里的建议是什么?我

我们正在构建一个webAPI服务,客户将使用AAD令牌访问该服务。因此,该服务需要对令牌进行身份验证,以确保其有效。 这是一个多租户场景

我查阅了AAD文档,没有什么问题。如果有人能帮助回答,我们将不胜感激

1) 根据我的理解,该服务将从AAD下载公共签名令牌并缓存它们。这些用于验证令牌,对吗

2) 刷新缓存签名令牌的建议间隔是多久?此外,如果AAD在刷新周期内旋转键,建议按需刷新

3) 根据我在中找到的AAD示例代码

由于计算机不信任AAD根证书,因此启用证书验证不起作用,这里的建议是什么?我们是否需要在受信任的存储中手动安装证书


4) 在AAD示例代码@中,它以同步方式下载这些签名令牌,是否有代码的异步版本?

AFAIK,请求将获得Azure AD发行的令牌,这些令牌通过私钥进行签名。web API将使用Azure AD的公钥自动验证令牌(OWIN组件)

要使用Visual Studio 2013之后的版本开发web API,无需手动验证令牌。下面是一段保护web API的代码:

public void ConfigureAuth(IAppBuilder app)
{
    app.UseWindowsAzureActiveDirectoryBearerAuthentication(
        new WindowsAzureActiveDirectoryBearerAuthenticationOptions
        {
            Audience = ConfigurationManager.AppSettings["ida:Audience"],
            Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
            TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters() { ValidateIssuer = false }
        });
}
是保护多租户web API的完整代码示例的链接

更新(支持不同控制器的密码和令牌身份验证)
谢谢你,菲。不幸的是,我认为我必须使用手动验证。例如,我想支持多个发卡机构租户。另外,我只验证某些控制器操作的令牌,对于其他操作,我有不同的身份验证模型。根据我的理解,如果你想用多个认证中间件来保护WebAPI,它应该是正确的。但是,无论用户使用哪种方式通过身份验证,web API都会返回结果。如果您希望使用相应的身份验证分离不同的API(更像“角色”管理,来自不同IDP的用户具有不同的角色),我们可以开发定制属性来验证特定的声明,以区分请求和请求。我还更新了帖子,添加了一个代码示例来演示这个场景。或者更简单的方法是为不同的身份验证开发两个web API控制器。感谢Fei提供的代码示例。初始化WindowsAzureActiveDirectoryBeareAuthenticationOptions时,传递颁发令牌的租户id。在我的情况下,客户可以属于不同的租户,因此发行人将是不同的否?我如何支持这一点?
public void ConfigureAuth(IAppBuilder app)
{
    app.UseWindowsAzureActiveDirectoryBearerAuthentication(
        new WindowsAzureActiveDirectoryBearerAuthenticationOptions
        {
            Audience = ConfigurationManager.AppSettings["ida:Audience"],
            Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
            TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters() { ValidateIssuer = false }
        });
}
public void ConfigureAuth(IAppBuilder app)
        {
            app.UseWindowsAzureActiveDirectoryBearerAuthentication(
                new WindowsAzureActiveDirectoryBearerAuthenticationOptions
                {
                    Audience = ConfigurationManager.AppSettings["ida:Audience"],
                    Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
                    TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters() { ValidateIssuer = false }
                });

            app.UsePasswordAuthentication();
        }

public class PasswordAuthorization : AuthorizeAttribute
{
    public override void OnAuthorization(HttpActionContext actionContext)
    {
        var principal = actionContext.RequestContext.Principal as ClaimsPrincipal;

        if (principal.FindFirst("authenticationType") == null)
        {
            actionContext.Response = new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.Unauthorized,
                Content = new StringContent("You are unauthorized to access this resource!")
            };

        }

    }
}

public class TokenAuthorization : AuthorizeAttribute
{

    public override void OnAuthorization(HttpActionContext actionContext)
    {
        var principal = actionContext.RequestContext.Principal as ClaimsPrincipal;

        if (principal.FindFirst("authenticationType") != null)
        {
            actionContext.Response = new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.Unauthorized,
                Content = new StringContent("You are unauthorized to access this resource!")
            };

        }

    }
}


public class PasswordAuthenticationOptions : AuthenticationOptions
{
    public PasswordAuthenticationOptions() : base("password")
    { }
}

public class PasswordAuthenticationHandler : AuthenticationHandler<PasswordAuthenticationOptions>
{
    protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
    {
        bool authorized = await Task<bool>.Run(() => IsAuthorised(Request.Headers));
        if (authorized)
        {
            AuthenticationProperties authProperties = new AuthenticationProperties();
            authProperties.IssuedUtc = DateTime.UtcNow;
            authProperties.ExpiresUtc = DateTime.UtcNow.AddDays(1);
            authProperties.AllowRefresh = true;
            authProperties.IsPersistent = true;
            IList<Claim> claimCollection = new List<Claim>
            {
                new Claim(ClaimTypes.Name, "Andras")
                , new Claim(ClaimTypes.Country, "Sweden")
                , new Claim(ClaimTypes.Gender, "M")
                , new Claim(ClaimTypes.Surname, "Nemes")
                , new Claim(ClaimTypes.Email, "hello@me.com")
                , new Claim(ClaimTypes.Role, "IT")
                , new Claim("authenticationType", "password")
            };
            ClaimsIdentity claimsIdentity = new ClaimsIdentity(claimCollection, "Custom");
            AuthenticationTicket ticket = new AuthenticationTicket(claimsIdentity, authProperties);
            return ticket;
        }

        return null;
    }

    private bool IsAuthorised(IHeaderDictionary requestHeaders)
    {
        string[] username,password;
        bool usernamePresent = requestHeaders.TryGetValue("username", out username);
        bool passwordPresent = requestHeaders.TryGetValue("password", out password);

        if (usernamePresent& passwordPresent)
        {
            if("user1".Equals(username[0])&&"pass".Equals(password[0]))
                return true;
        }

        return false;
    }
}


public class PasswordAuthMiddleware : AuthenticationMiddleware<PasswordAuthenticationOptions>
{
    public PasswordAuthMiddleware(OwinMiddleware nextMiddleware, PasswordAuthenticationOptions authOptions)
        : base(nextMiddleware, authOptions)
    { }

    protected override AuthenticationHandler<PasswordAuthenticationOptions> CreateHandler()
    {
        return new PasswordAuthenticationHandler();
    }
}

public static class PassworAuthenticationExtension
{
    public static void UsePasswordAuthentication(this IAppBuilder appBuilder)
    {
        appBuilder.Use<PasswordAuthMiddleware>(new PasswordAuthenticationOptions());
    }
}
[PasswordAuthorization]
public class Values2Controller : ApiController
{
    // GET: api/Values2
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    } 
}
[TokenAuthorization]
public class ValuesController : ApiController
{ 
    // GET api/values
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }
}
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
    Audience = ConfigurationManager.AppSettings["ida:Audience"],
    Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
    TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters() {
        ValidateIssuer = true,
        ValidIssuers =new string[] { "https://sts.windows.net/{tenantId}/" } 
    }
});