Registrace a onboarding tenanta
Tento článek popisuje, jak implementovat proces registrace ve vícetenantové aplikaci, která umožňuje zákazníkovi zaregistrovat si svou organizaci pro vaši aplikaci.
Proces registrace je možné implementovat z několika důvodů:
- Povolte správci AD souhlas s používáním aplikace v celé organizaci zákazníka.
- Shromažďovat platební karty nebo jiné informace o zákazníku.
- Proveďte jakékoli nastavení pro jednoho tenanta, které vaše aplikace potřebuje.
Souhlas správce a oprávnění Azure AD
K ověření pomocí Azure AD potřebuje aplikace přístup k adresáři uživatele. Aplikace potřebuje alespoň oprávnění ke čtení profilu uživatele. Při prvním přihlášení uživatele se v Azure AD zobrazí stránka souhlasu se seznamem požadovaných oprávnění. Kliknutím na Přijmout uživatel udělí oprávnění k aplikaci.
Ve výchozím nastavení se souhlas uděluje pro uživatele. Stránka souhlasu se zobrazí každému uživateli, který se přihlásí. Azure AD ale podporuje také souhlas správce, který umožňuje správci AD vysou souhlas pro celou organizaci.
Při použití toku souhlasu správce se na stránce souhlasu zobrazí, že správce AD uděluje oprávnění jménem celého tenanta:

Když správce klikne na Přijmout, jinými uživateli ve stejném tenantovi se budou moci přihlásit a Azure AD přeskočí obrazovku pro udělení souhlasu.
Souhlas správce může udělit pouze správce, protože uděluje oprávnění jménem celé organizace. Pokud se uživatel bez oprávnění správce pokusí provést ověření pomocí toku souhlasu správce, Azure AD zobrazí chybu:

Pokud aplikace později vyžaduje další oprávnění, zákazník se bude muset znovu zaregistrovat a udělit souhlas s aktualizovanými oprávněními.
Implementace registrace tenanta
Pro aplikaci Tailspin Surveys jsme definovali několik požadavků na proces registrace:
- Tenant se musí zaregistrovat, aby se uživatelé mohli přihlásit.
- Registrace používá tok souhlasu správce.
- Registrace přidá tenanta uživatele do databáze aplikace.
- Jakmile se tenant přihlásí, aplikace zobrazí stránku pro onboarding.
V této části vás provedeme implementací procesu registrace. Je důležité pochopit, že "registrace" a "přihlášení" je koncept aplikace. Během toku ověřování Azure AD ze své podstaty neví, jestli se uživatel přihlašuje. Sledování kontextu je na aplikaci.
Když anonymní uživatel navštíví aplikaci Surveys, zobrazí se uživateli dvě tlačítka, jedno pro přihlášení a jedno pro registraci vaší společnosti (registrace).

Tato tlačítka volat akce ve AccountController třídě.
Akce SignIn vrátí hodnotu ChallengeResult, která způsobí, že Připojení OpenID přesměruje middleware na ověřovací koncový bod. Toto je výchozí způsob aktivace ověřování v ASP.NET Core.
[AllowAnonymous]
public IActionResult SignIn()
{
return new ChallengeResult(
OpenIdConnectDefaults.AuthenticationScheme,
new AuthenticationProperties
{
IsPersistent = true,
RedirectUri = Url.Action("SignInCallback", "Account")
});
}
Teď akci SignUp porovnejte:
[AllowAnonymous]
public IActionResult SignUp()
{
var state = new Dictionary<string, string> { { "signup", "true" }};
return new ChallengeResult(
OpenIdConnectDefaults.AuthenticationScheme,
new AuthenticationProperties(state)
{
RedirectUri = Url.Action(nameof(SignUpCallback), "Account")
});
}
Podobně SignIn jako akce vrátí také SignUp ChallengeResult . Tentokrát ale přidáme do souboru informace o AuthenticationProperties stavu ChallengeResult v souboru :
- signup: Logický příznak, který označuje, že uživatel zahájil proces registrace.
Informace o stavu v AuthenticationProperties se přičtou do openID Připojení [stavu,] který se během toku ověřování zaokrouhlí.

Jakmile se uživatel ověří ve službě Azure AD a přesměruje se zpět do aplikace, lístek ověřování bude obsahovat stav. Tento fakt používáme k tomu, aby se hodnota "registrace" uchová v celém toku ověřování.
Přidání výzvy k udělení souhlasu správce
Ve službě Azure AD se tok souhlasu správce aktivuje přidáním parametru prompt do řetězce dotazu v žádosti o ověření:
/authorize?prompt=admin_consent&...
Aplikace Surveys přidá výzvu během RedirectToIdentityProvider události. Tato událost se volá těsně před přesměrováním middlewaru na ověřovací koncový bod.
public override Task RedirectToIdentityProvider(RedirectContext context)
{
if (context.IsSigningUp())
{
context.ProtocolMessage.Prompt = "admin_consent";
}
_logger.RedirectToIdentityProvider();
return Task.FromResult(0);
}
Nastavení říká middlewaru, aby do požadavku na ověření přidat ProtocolMessage.Prompt parametr prompt.
Všimněte si, že výzva je potřeba jenom během registrace. Pravidelné přihlašování by ho nemělo zahrnovat. Pro rozlišení mezi nimi zkontrolujeme hodnotu signup ve stavu ověřování. Tuto podmínku kontroluje následující rozšiřující metoda:
internal static bool IsSigningUp(this AuthenticationProperties properties)
{
Guard.ArgumentNotNull(properties, nameof(properties));
string signupValue = string.Empty;
// Check the HTTP context and convert to string
if ((properties == null) ||
(!properties.Items.TryGetValue("signup", out signupValue)))
{
return false;
}
// We have found the value, so see if it's valid
bool isSigningUp;
if (!bool.TryParse(signupValue, out isSigningUp))
{
// The value for signup is not a valid boolean, throw
throw new InvalidOperationException($"'{signupValue}' is an invalid boolean value");
}
return isSigningUp;
}
Registrace tenanta
Aplikace Surveys ukládá některé informace o jednotlivých tenantech a uživatelích v databázi aplikace.

V tabulce Tenant je IssuerValue hodnotou deklarace identity vystavitele pro tenanta. Pro Azure AD je to https://sts.windows.net/<tentantID> a poskytuje jedinečnou hodnotu pro tenanta.
Když se nový tenant přihlásí, aplikace Surveys zapíše do databáze záznam tenanta. K tomu dochází uvnitř AuthenticationValidated události . (Před touto událostí to nedělejte, protože token ID se ještě neověřuje, takže nemůžete důvěřovat hodnotám deklarace identity. Viz [Ověřování.]
Tady je příslušný kód z aplikace Surveys:
public override async Task TokenValidated(TokenValidatedContext context)
{
var principal = context.Principal;
var userId = principal.GetObjectIdentifierValue();
var tenantManager = context.HttpContext.RequestServices.GetService<TenantManager>();
var userManager = context.HttpContext.RequestServices.GetService<UserManager>();
var issuerValue = context.SecurityToken.Issuer;
_logger.AuthenticationValidated(userId, issuerValue);
// Normalize the claims first.
NormalizeClaims(principal);
var tenant = await tenantManager.FindByIssuerValueAsync(issuerValue);
if (context.Properties.IsSigningUp())
{
if (tenant == null)
{
tenant = await SignUpTenantAsync(context, tenantManager)
.ConfigureAwait(false);
}
// In this case, we need to go ahead and set up the user signing us up.
await CreateOrUpdateUserAsync(context.Ticket, userManager, tenant)
.ConfigureAwait(false);
}
else
{
if (tenant == null)
{
_logger.UnregisteredUserSignInAttempted(userId, issuerValue);
throw new SecurityTokenValidationException($"Tenant {issuerValue} is not registered");
}
await CreateOrUpdateUserAsync(context.Principal, userManager, tenant)
.ConfigureAwait(false);
}
}
Tento kód udělá toto:
- Zkontrolujte, jestli hodnota vystavitele tenanta už je v databázi. Pokud se tenant neza zaregistroval,
FindByIssuerValueAsyncvrátí hodnotu null. - Pokud se uživatel přihlašuje:
- Přidejte tenanta do databáze (
SignUpTenantAsync). - Přidejte ověřeného uživatele do databáze (
CreateOrUpdateUserAsync).
- Přidejte tenanta do databáze (
- Jinak dokončete normální přihlašovací tok:
- Pokud se vystavitel tenanta v databázi nenašel, znamená to, že tenant není zaregistrovaný a zákazník se musí zaregistrovat. V takovém případě vyvolá výjimku, která způsobí selhání ověřování.
- V opačném případě vytvořte pro tohoto uživatele záznam databáze, pokud ještě neexistuje (
CreateOrUpdateUserAsync).
Tady je SignUpTenantAsync metoda, která přidá tenanta do databáze.
private async Task<Tenant> SignUpTenantAsync(TokenValidatedContext context, TenantManager tenantManager)
{
Guard.ArgumentNotNull(context, nameof(context));
Guard.ArgumentNotNull(tenantManager, nameof(tenantManager));
var principal = context.Principal;
var issuerValue = principal.GetIssuerValue();
var tenant = new Tenant
{
IssuerValue = issuerValue,
Created = DateTimeOffset.UtcNow
};
try
{
await tenantManager.CreateAsync(tenant)
.ConfigureAwait(false);
}
catch(Exception ex)
{
_logger.SignUpTenantFailed(principal.GetObjectIdentifierValue(), issuerValue, ex);
throw;
}
return tenant;
}
Tady je souhrn celého toku registrace v aplikaci Surveys:
- Uživatel klikne na tlačítko Zaregistrovat se.
- Akce
AccountController.SignUpvrátí výsledek výzvy. Stav ověřování zahrnuje hodnotu "registrace". - V
RedirectToAuthenticationEndpointudálosti přidejteadmin_consentpříkazový řádek. - OpenID Připojení middleware přesměruje do Azure AD a uživatel se ověří.
- V
AuthenticationValidatedpřípadě vyhledejte stav "registrace". - Přidejte tenanta do databáze.
Vzorek kódu