使用 OWIN Active Directory 承载令牌启用多个租户
Enabling multiple tenants using OWIN Active Directory bearer tokens
我最近开始使用 Azure Active Directory 来根据我在 AngularJS.
上构建的网站对用户进行身份验证
使用博客和 sample code on GitHub, I've gotten it working with single-tenant using a combination of ADAL.js and Katana's Bearer Token AD integration。
但是,我现在 运行 遇到支持多个租户的一些问题。
我已经设置了一个页面来显示 ADAL 看到的用户(通过根作用域的 userInfo
找到),以及调用我的服务器并由 OWIN 接收,并序列化 context.Authentication.User
.
客户端,似乎一切正常。我可以用我的任何租户登录,它给了我我期望的对象(填充了 isAuthenticated: true
、username
,以及 profile
上描述用户的各种属性,登录和租户)。
这是在客户端完成的,方法是在我的 adalAuthenticationServiceProvider.init
调用中去掉 tenant
参数,如文档中所述。
服务器端,但是,UseWindowsAzureActiveDirectoryBearerAuthentication
方法不喜欢 Tenant
没有值(因为它会抛出异常)。我为此尝试了一些值,包括我的应用程序最初注册的租户,以及我最喜欢的逻辑 "common," 但无论我在那里放什么(除非它是我尝试登录的租户在里面,如果我的 ADAL 是与那个租户一起设置的),它似乎只是跳过这个。
就其价值而言,实际的 API 调用在 [Authorize]
过滤器上失败并返回 401,这告诉我这不是我的 OWIN 拦截器的问题。
如何告诉 UseWindowsAzureActiveDirectoryBearerAuthentication
支持多租户身份验证?
我是在写问题的时候想出来的。我认为。但我花了一整天的时间发现几乎没有关于此事的文件,所以我想我还是 post 它。
我的解决方案(通过 yet another blog post 找到)是将 ValidateIssuer = false
作为参数包含在内。这是有道理的,因为我们不再想验证给我们令牌的租户是否就是我们列出的租户。
这是我解决问题的代码。
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
TokenValidationParameters = new TokenValidationParameters
{
ValidAudience = ConfigurationManager.AppSettings["ida:Audience"],
ValidateIssuer = false // This line made it work
},
AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
Tenant = "common" // I don't know whether this has any impact,
// but it's a required parameter regardless.
});
如果其他人想要纠正我,如果这有任何不可预见的情况,我会很高兴 - 当您进行身份验证时,将 "validate" 开关切换到关闭有点令人生畏。但我认为这一切都足够有意义。
在开发多租户应用程序时,您不能再 100% 依赖默认的身份验证逻辑。默认身份验证逻辑假定您在要接收令牌的地方声明了 azure AD 租户表单,并且将强制执行仅接受该租户的令牌表单。这是通过检查与每个租户关联的元数据文档来完成的,其中包含(除其他事项外)租户本身的标识符 - 该标识符必须存在于您收到的令牌中,在 iss 声明中:任何其他值意味着令牌来自另一个租户,因此必须拒绝。
根据定义,多租户应用程序必须接受来自多个租户的令牌。这是通过使用参数端点(公共端点,参见 this post)来完成的,它允许您 "late bind" 哪个租户将用于颁发令牌。然而,公共端点将提供一个通用元数据文档,该文档不能包含特定的 iss 值:相反,它包含一个占位符,该占位符在运行时将始终替换为您实际从中获得令牌的租户的颁发者标识符。
这意味着在多租户应用程序中,您必须 接管 租户验证逻辑。如果您只是在调试,您可以将其关闭,就像您所做的那样 - 这将阻止默认发行者验证逻辑启动并拒绝传入令牌,因为它的 iss 值与为 common 找到的占位符不对应。然而,在更实际的情况下,您将在 TokenValidationParameters.IssuerValidator
委托中编写自己的逻辑。例如,您可能希望将传入令牌中的 iss 值与购买每月订阅服务的租户列表进行比较。 HTH
我最近开始使用 Azure Active Directory 来根据我在 AngularJS.
上构建的网站对用户进行身份验证使用博客和 sample code on GitHub, I've gotten it working with single-tenant using a combination of ADAL.js and Katana's Bearer Token AD integration。
但是,我现在 运行 遇到支持多个租户的一些问题。
我已经设置了一个页面来显示 ADAL 看到的用户(通过根作用域的 userInfo
找到),以及调用我的服务器并由 OWIN 接收,并序列化 context.Authentication.User
.
客户端,似乎一切正常。我可以用我的任何租户登录,它给了我我期望的对象(填充了 isAuthenticated: true
、username
,以及 profile
上描述用户的各种属性,登录和租户)。
这是在客户端完成的,方法是在我的 adalAuthenticationServiceProvider.init
调用中去掉 tenant
参数,如文档中所述。
服务器端,但是,UseWindowsAzureActiveDirectoryBearerAuthentication
方法不喜欢 Tenant
没有值(因为它会抛出异常)。我为此尝试了一些值,包括我的应用程序最初注册的租户,以及我最喜欢的逻辑 "common," 但无论我在那里放什么(除非它是我尝试登录的租户在里面,如果我的 ADAL 是与那个租户一起设置的),它似乎只是跳过这个。
就其价值而言,实际的 API 调用在 [Authorize]
过滤器上失败并返回 401,这告诉我这不是我的 OWIN 拦截器的问题。
如何告诉 UseWindowsAzureActiveDirectoryBearerAuthentication
支持多租户身份验证?
我是在写问题的时候想出来的。我认为。但我花了一整天的时间发现几乎没有关于此事的文件,所以我想我还是 post 它。
我的解决方案(通过 yet another blog post 找到)是将 ValidateIssuer = false
作为参数包含在内。这是有道理的,因为我们不再想验证给我们令牌的租户是否就是我们列出的租户。
这是我解决问题的代码。
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
TokenValidationParameters = new TokenValidationParameters
{
ValidAudience = ConfigurationManager.AppSettings["ida:Audience"],
ValidateIssuer = false // This line made it work
},
AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
Tenant = "common" // I don't know whether this has any impact,
// but it's a required parameter regardless.
});
如果其他人想要纠正我,如果这有任何不可预见的情况,我会很高兴 - 当您进行身份验证时,将 "validate" 开关切换到关闭有点令人生畏。但我认为这一切都足够有意义。
在开发多租户应用程序时,您不能再 100% 依赖默认的身份验证逻辑。默认身份验证逻辑假定您在要接收令牌的地方声明了 azure AD 租户表单,并且将强制执行仅接受该租户的令牌表单。这是通过检查与每个租户关联的元数据文档来完成的,其中包含(除其他事项外)租户本身的标识符 - 该标识符必须存在于您收到的令牌中,在 iss 声明中:任何其他值意味着令牌来自另一个租户,因此必须拒绝。
根据定义,多租户应用程序必须接受来自多个租户的令牌。这是通过使用参数端点(公共端点,参见 this post)来完成的,它允许您 "late bind" 哪个租户将用于颁发令牌。然而,公共端点将提供一个通用元数据文档,该文档不能包含特定的 iss 值:相反,它包含一个占位符,该占位符在运行时将始终替换为您实际从中获得令牌的租户的颁发者标识符。
这意味着在多租户应用程序中,您必须 接管 租户验证逻辑。如果您只是在调试,您可以将其关闭,就像您所做的那样 - 这将阻止默认发行者验证逻辑启动并拒绝传入令牌,因为它的 iss 值与为 common 找到的占位符不对应。然而,在更实际的情况下,您将在 TokenValidationParameters.IssuerValidator
委托中编写自己的逻辑。例如,您可能希望将传入令牌中的 iss 值与购买每月订阅服务的租户列表进行比较。 HTH