У меня есть приложение, которое я хотел бы предоставить как можно большему количеству пользователей. Для этого я следую указаниям , как описано здесь, для подключения моего приложения к 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 с облаком.
Моя страница обнаружения домашней области выдаст GET по следующему URL-адресу, чтобы определить, следует ли использовать домен LiveID или AzureAD.
https://login.microsoftonline.com/[email protected]
или 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);
}
}