【发布时间】:2019-05-23 08:29:56
【问题描述】:
我使用 Azure ADB2C 进行身份验证和授权,并使用 Open Id Connect 流。我需要将用户重定向到应用程序主页,并将检索到的访问令牌附加到主页 url 作为来自“OnAuthorizationCodeReceived”的查询参数。但这不起作用。下面是我的代码。
通过这样做,我打算从重定向 URL 中捕获访问令牌和 id 令牌。 这是一个单页应用程序。我尝试了 MSAL.js,但它在浏览器兼容性方面存在问题,甚至有时在不同的身份提供者中也存在问题。所以我决定从 c# 后端用户打开 id
public static class AzureAdB2CAuthenticationBuilderExtensions
{
public static AuthenticationBuilder AddAzureAdB2C(this AuthenticationBuilder builder)
=> builder.AddAzureAdB2C(_ =>
{
});
public static AuthenticationBuilder AddAzureAdB2C(this AuthenticationBuilder builder, Action<AzureAdB2COptions> configureOptions)
{
builder.Services.Configure(configureOptions);
builder.Services.AddSingleton<IConfigureOptions<OpenIdConnectOptions>, OpenIdConnectOptionsSetup>();
builder.AddOpenIdConnect();
return builder;
}
public class OpenIdConnectOptionsSetup : IConfigureNamedOptions<OpenIdConnectOptions>
{
public OpenIdConnectOptionsSetup(IOptions<AzureAdB2COptions> b2cOptions)
{
AzureAdB2COptions = b2cOptions.Value;
}
public AzureAdB2COptions AzureAdB2COptions { get; set; }
public void Configure(string name, OpenIdConnectOptions options)
{
options.ClientId = AzureAdB2COptions.ClientId;
options.Authority = AzureAdB2COptions.Authority;
options.UseTokenLifetime = true;
//options.CallbackPath = new Microsoft.AspNetCore.Http.PathString("/console/home");
options.TokenValidationParameters = new TokenValidationParameters() { SaveSigninToken=true, NameClaimType = "name" };
options.SaveTokens = true;
options.Events = new OpenIdConnectEvents()
{
OnRedirectToIdentityProvider = OnRedirectToIdentityProvider,
OnRemoteFailure = OnRemoteFailure,
OnAuthorizationCodeReceived = OnAuthorizationCodeReceived,
OnTokenValidated= OnTokenValidated,
OnTokenResponseReceived= OnTokenResponseReceived
};
}
public void Configure(OpenIdConnectOptions options)
{
Configure(Options.DefaultName, options);
}
public Task OnRedirectToIdentityProvider(RedirectContext context)
{
var defaultPolicy = AzureAdB2COptions.DefaultPolicy;
if (context.Properties.Items.TryGetValue(AzureAdB2COptions.PolicyAuthenticationProperty, out var policy) &&
!policy.Equals(defaultPolicy))
{
context.ProtocolMessage.Scope = OpenIdConnectScope.OpenIdProfile;
context.ProtocolMessage.ResponseType = OpenIdConnectResponseType.IdToken;
context.ProtocolMessage.IssuerAddress = context.ProtocolMessage.IssuerAddress.ToLower().Replace(defaultPolicy.ToLower(), policy.ToLower());
context.Properties.Items.Remove(AzureAdB2COptions.PolicyAuthenticationProperty);
}
else if (!string.IsNullOrEmpty(AzureAdB2COptions.ApiUrl))
{
context.ProtocolMessage.Scope += $" offline_access {AzureAdB2COptions.ApiScopes}";
context.ProtocolMessage.ResponseType = OpenIdConnectResponseType.CodeIdToken;
}
return Task.FromResult(0);
}
public Task OnRemoteFailure(RemoteFailureContext context)
{
context.HandleResponse();
// Handle the error code that Azure AD B2C throws when trying to reset a password from the login page
// because password reset is not supported by a "sign-up or sign-in policy"
if (context.Failure is OpenIdConnectProtocolException && context.Failure.Message.Contains("AADB2C90118"))
{
// If the user clicked the reset password link, redirect to the reset password route
context.Response.Redirect("/Session/ResetPassword");
}
else if (context.Failure is OpenIdConnectProtocolException && context.Failure.Message.Contains("access_denied"))
{
context.Response.Redirect("/");
}
else
{
context.Response.Redirect("/Home/Error?message=" + context.Failure.Message);
}
return Task.FromResult(0);
}
public Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedContext context)
{
// Use MSAL to swap the code for an access token
// Extract the code from the response notification
var code = context.ProtocolMessage.Code;
string signedInUserID = context.Principal.FindFirst(ClaimTypes.NameIdentifier).Value;
TokenCache userTokenCache = new MSALSessionCache(signedInUserID, context.HttpContext).GetMsalCacheInstance();
ConfidentialClientApplication cca = new ConfidentialClientApplication(AzureAdB2COptions.ClientId, AzureAdB2COptions.Authority, AzureAdB2COptions.RedirectUri, new ClientCredential(AzureAdB2COptions.ClientSecret), userTokenCache, null);
try
{
List<string> apiScopes = new List<string>();
AuthenticationResult result = cca.AcquireTokenByAuthorizationCodeAsync(code, AzureAdB2COptions.ApiScopes.Split(' ')).Result;
//context.HandleResponse();
context.HandleCodeRedemption(result.AccessToken, result.IdToken);
context.Response.Redirect("http://localhost:8836/console/home?id_token="+result.IdToken+"&access_token="+result.AccessToken);
return Task.FromResult(0);
//context.HandleCodeRedemption(result.AccessToken, result.IdToken);
}
catch (Exception ex)
{
//TODO: Handle
throw;
}
}
public Task OnTokenValidated(TokenValidatedContext context)
{
try
{
return Task.FromResult(0);
}
catch (Exception ex)
{
throw;
}
}
public Task OnTokenResponseReceived(TokenResponseReceivedContext context)
{
try
{
var cntxt = context;
context.ProtocolMessage.RedirectUri = "/console/home";
context.Response.Redirect("/Home/Error?message=test");
return Task.FromResult(0);
}
catch (Exception ex)
{
throw;
}
}
}
}
这是我的创业课
public void ConfigureServices(IServiceCollection services)
{
services.Configure<AzureAdB2COptions>(Configuration.GetSection("Authentication:AzureAdB2C"));
services.AddSingleton<IConfigureOptions<OpenIdConnectOptions>, OpenIdConnectOptionsSetup>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddAzureAdB2C(options => Configuration.Bind("Authentication:AzureAdB2C", options))
.AddCookie();
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
services.AddMvc();
// Adds a default in-memory implementation of IDistributedCache.
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromHours(1);
options.CookieHttpOnly = true;
});
}
【问题讨论】:
-
添加您订阅此事件的代码。
-
@Max hi max,当我在 login.microsoftonline.com B2C 站点输入我的凭据时,此 OnAuthorizationCodeReceieved 触发。
-
@Max Hi max 我更新了代码。请看看:)
-
这看起来像一个 IConfigureNamedOptions。 1. 可以发全班吗? 2.你能发布你绑定这个类的代码吗? 3. 有没有试过断点看是否输入代码? 4.“它不起作用”是什么意思?
-
@Max 更新了代码。是的,Max 尝试过调试。不起作用意味着它不会将用户重定向到我要求重定向的页面(“console/home”+token)
标签: asp.net-core openid-connect azure-ad-b2c