ما سرویس توکن را برای استفاده از گوگل به عنوان سیستم احراز هویت بیرونی تنظیم کرده ایم. قبل از اینکه برنامه را آزمایش کنیم، بیایید کنترلر Account را که در پوشه QuickStart قرار دارد، بررسی کنیم و ببینیم چه بخش های دیگری وجود دارند. متد یا همان اکشن login نقطه شروع فرایند برای این احراز هویت است.
در صورتی که از احراز هویت خارجی استفاده می کنیم به سمت کنترلر External و متد Challenge هدایت می شویم. به سراغ متد Challenge می رویم، در این متد به بخش زیر می رسیم:/// <summary> /// Entry point into the login workflow /// </summary> [HttpGet] public async Task<IActionResult> Login(string returnUrl){// build a model so we know what to show on the login page var vm = await BuildLoginViewModelAsync(returnUrl); if (vm.IsExternalLoginOnly){// we only have one option for logging in and it's an external provider return RedirectToAction("Challenge", "External", new { provider = vm.ExternalLoginScheme, returnUrl });}return View(vm);}
// start challenge and roundtrip the return URL and scheme
var props = new AuthenticationProperties
{
RedirectUri = Url.Action(nameof(Callback)),
Items =
{
{ "returnUrl", returnUrl },
{ "scheme", scheme },
}
};
return Challenge(props, scheme);
اینجاست که ما با استفاده از متد Challenge میان افزار احراز هویت خارجی را
فراخوانی می کنیم. ما به متد مربوطه، نام ارائه دهنده خارجی و آدرس صفحه ای
را می دهیم که بعد از موفقیت آمیز بودن ورود، به آن صفحه هدایت می شویم.
/// <summary>
/// Post processing of external authentication
/// </summary>
[HttpGet]
public async Task<IActionResult> Callback()
{
// read external identity from the temporary cookie
var result = await HttpContext.AuthenticateAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);
if (result?.Succeeded != true)
{
throw new Exception("External authentication error");
}
if (_logger.IsEnabled(LogLevel.Debug))
{
var externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}");
_logger.LogDebug("External claims: {@claims}", externalClaims);
}
// lookup our user and external provider info
var (user, provider, providerUserId, claims) = FindUserFromExternalProvider(result);
if (user == null)
{
// this might be where you might initiate a custom workflow for user registration
// in this sample we don't show how that would be done, as our sample implementation
// simply auto-provisions new external user
user = AutoProvisionUser(provider, providerUserId, claims);
}
// this allows us to collect any additional claims or properties
// for the specific protocols used and store them in the local auth cookie.
// this is typically used to store data needed for signout from those protocols.
var additionalLocalClaims = new List<Claim>();
var localSignInProps = new AuthenticationProperties();
ProcessLoginCallbackForOidc(result, additionalLocalClaims, localSignInProps);
//ProcessLoginCallbackForWsFed(result, additionalLocalClaims, localSignInProps);
//ProcessLoginCallbackForSaml2p(result, additionalLocalClaims, localSignInProps);
// issue authentication cookie for user
var isuser = new IdentityServerUser(user.SubjectId)
{
DisplayName = user.Username,
IdentityProvider = provider,
AdditionalClaims = additionalLocalClaims
};
await HttpContext.SignInAsync(isuser, localSignInProps);
// delete temporary cookie used during external authentication
await HttpContext.SignOutAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);
// retrieve return URL
var returnUrl = result.Properties.Items["returnUrl"] ?? "~/";
// check if external login is in the context of an OIDC request
var context = await _interaction.GetAuthorizationContextAsync(returnUrl);
await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.SubjectId, user.Username, true, context?.ClientId));
if (context != null)
{
if (context.IsNativeClient())
{
// The client is native, so this change in how to
// return the response is for better UX for the end user.
return this.LoadingPage("Redirect", returnUrl);
}
}
return Redirect(returnUrl);
}