我无法找出或找到关于如何在Blazor WASM应用程序中使用两个不同的OIDC提供程序的文档。所有的"食谱",文档和库都显示了如何使用单个提供程序,并在组件和javascript中加载MSAL OIDC/OAUTH魔法。
谁能给我指出一个资源或例子,超越MS学习教程或指示我如何可以让用户之间的身份提供者选择。IdP只需要返回一个id_token。我知道我可以通过源代码,我只是希望在魔术和源代码之间有一个中间阶段。
我认为我可能能够将方案传递给RemoteAuthenticatorView
,但我认为这是不可能的。我也在探索是否手动设置RemoteAuthenticationApplicationPathsOptions
指向特定的IdP作为前进的方向。
欢迎有其他想法
您不需要更改RemoteAuthenticatorView
,您需要更改自己编写的登录页面,而不是使用标准的认证/登录页面;url。
您必须创建一个登录Blazor页面
@page "/login"
@using BlazorApp1.Shared;
@inject NavigationManager Navigation
@foreach (var item in identityProviders)
{
<button class="btn btn-primary" @onclick="() => ExternalLogin(item)">@item.DisplayName</button>
}
@code {
List<IdentityProvider> identityProviders = new List<IdentityProvider>();
protected override async Task OnInitializedAsync()
{
identityProviders.Add(new IdentityProvider { AuthenticationScheme = "oidc", DisplayName = "Google" });
identityProviders.Add(new IdentityProvider { AuthenticationScheme = "oidc-idserver", DisplayName = "Azure AD" });
}
private void ExternalLogin(IdentityProvider schema)
{
Navigation.NavigateTo("/pages/external?returnurl=/&schema=" + schema.AuthenticationScheme, true);
}
}
然后在服务器上你可以创建一个标准的Asp。Net Web页面来处理登录请求,获取模式并重定向到正确的身份提供者:
[AllowAnonymous]
[IgnoreAntiforgeryToken]
public class ExternalModel : PageModel
{
private readonly SignInManager<ApplicationUser> _signInManager;
public ExternalModel(SignInManager<ApplicationUser> signInManager)
{
_signInManager = signInManager;
}
public IActionResult OnGetAsync(string returnUrl, string schema)
{
returnUrl = (returnUrl == null) ? "/" : returnUrl;
if (schema != "")
{
var redirectUrl = Url.Page("./External", pageHandler: "Callback", values: new { returnUrl });
var properties = _signInManager.ConfigureExternalAuthenticationProperties(schema, redirectUrl);
return new ChallengeResult(schema, properties);
}
else
{
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return new EmptyResult();
}
}
public async Task<IActionResult> OnGetCallbackAsync(string returnUrl = null, string remoteError = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (remoteError != null)
{
var errorMessage = $"Error from external provider: {remoteError}";
return RedirectToPage("./Login", new { ReturnUrl = returnUrl });
}
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
var errorMessage = "Error loading external login information.";
return RedirectToPage("./Login", new { ReturnUrl = returnUrl });
}
// Sign in the user with this external login provider if the user already has a login.
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true);
if (result.Succeeded)
{
return LocalRedirect(returnUrl);
}
if (result.IsLockedOut)
{
return RedirectToPage("./Lockout");
}
}
}
这是一个不完整的例子,但是要理解这个思想