我有一个应用程序,我想向尽可能多的用户公开。为此,我按照此处说明的说明 将我的应用程序连接到 Azure Active Directory,并按照这些说明的变体将AAD 连接到 Azure ACS 2.0。
Azure ACS 2.0 将处理所有联合域和 Microsoft 帐户(以前的 LiveID 或 Passport)。它还将处理 Facebook、Twitter 和其他 OAuth 服务。
Azure Active Directory 将处理 Office 365,以及将其公司 Active Directory 同步到云的任何人。
我的主领域发现页面将在以下 URL 发出 GET 以确定是否应使用 LiveID 或 AzureAD 域。
https://login.microsoftonline.com/GetUserRealmExtended.srf?login=EMAIL@COMPANY.com
或 http://odc.officeapps.live.com/odc/emailhrd/getidp?hm=0&emailAddress=USER%COMPANY.com
如果用户不存在,我将使用 Azure ACS 与该公司的联合。缺少它,用户将无法登录。
现在我解释了我的配置,我打算让 Windows Identity Foundation (WIF) 允许来自 ACS 2.0 和 ADFS 的身份验证。
问题
- 如何获得 WIF 4.5,特别是 ValidatingIssuerNameRegistry 以正确处理对多个 IDP 的多个信任?
下面是 VS2013 在将应用程序与 Azure Active Directory 联合时附带的代码。它响应所有联合请求并执行我不理解的其他事情。有关此类的任何链接或信息都会有所帮助
public class DatabaseIssuerNameRegistry : ValidatingIssuerNameRegistry
{
public static bool ContainsTenant(string tenantId)
{
using (TenantDbContext context = new TenantDbContext())
{
return context.Tenants
.Where(tenant => tenant.Id == tenantId)
.Any();
}
}
public static bool ContainsKey(string thumbprint)
{
using (TenantDbContext context = new TenantDbContext())
{
return context.IssuingAuthorityKeys
.Where(key => key.Id == thumbprint)
.Any();
}
}
public static void RefreshKeys(string metadataLocation)
{
IssuingAuthority issuingAuthority = ValidatingIssuerNameRegistry.GetIssuingAuthority(metadataLocation);
bool newKeys = false;
foreach (string thumbprint in issuingAuthority.Thumbprints)
{
if (!ContainsKey(thumbprint))
{
newKeys = true;
break;
}
}
if (newKeys)
{
using (TenantDbContext context = new TenantDbContext())
{
context.IssuingAuthorityKeys.RemoveRange(context.IssuingAuthorityKeys);
foreach (string thumbprint in issuingAuthority.Thumbprints)
{
context.IssuingAuthorityKeys.Add(new IssuingAuthorityKey { Id = thumbprint });
}
context.SaveChanges();
}
}
}
public static bool TryAddTenant(string tenantId, string signupToken)
{
if (!ContainsTenant(tenantId))
{
using (TenantDbContext context = new TenantDbContext())
{
SignupToken existingToken = context.SignupTokens.Where(token => token.Id == signupToken).FirstOrDefault();
if (existingToken != null)
{
context.SignupTokens.Remove(existingToken);
context.Tenants.Add(new Tenant { Id = tenantId });
context.SaveChanges();
return true;
}
}
}
return false;
}
public static void AddSignupToken(string signupToken, DateTimeOffset expirationTime)
{
using (TenantDbContext context = new TenantDbContext())
{
context.SignupTokens.Add(new SignupToken
{
Id = signupToken,
ExpirationDate = expirationTime
});
context.SaveChanges();
}
}
public static void CleanUpExpiredSignupTokens()
{
DateTimeOffset now = DateTimeOffset.UtcNow;
using (TenantDbContext context = new TenantDbContext())
{
IQueryable<SignupToken> tokensToRemove = context.SignupTokens.Where(token => token.ExpirationDate <= now);
if (tokensToRemove.Any())
{
context.SignupTokens.RemoveRange(tokensToRemove);
context.SaveChanges();
}
}
}
protected override bool IsThumbprintValid(string thumbprint, string issuer)
{
string issuerID = issuer.TrimEnd('/').Split('/').Last();
return ContainsTenant(issuerID) &&
ContainsKey(thumbprint);
}
}