asp net core项目使用Cookie认证的MVC控制器和使用Bearer的api端点

Ner*_*ero 6 asp.net single-sign-on asp.net-web-api asp.net-core

我正在使用ASP .net CORE开发一个项目,我们有Angular 2和MVC以及API,需要受Azure AD保护.

Home/Index MVC控制器将启动Angular 2 SPA,Home/Index需要通过cookie身份验证进行保护.我设法使用OpenIdConnectAuthentication - OnAuthorizationCodeReceived事件获取令牌.

我需要使用基于Cookie的身份验证和使用承载身份验证的API来保护MVC控制器(除了Home/Index之外还有更少的控制器),我可以从API获取令牌到Angular,然后在每次后续API调用时使用该令牌.

在不久的将来,将会有使用Bearer令牌调用相同API端点的移动应用程序.

这是我的出发点:https: //docs.microsoft.com/en-us/azure/active-directory/active-directory-appmodel-v2-overview

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
   services.AddMvc().AddJsonOptions(config => { config.SerializerSettings.ContractResolver = new DefaultContractResolver(); });

   services.AddAuthentication(sharedOptions => sharedOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme);
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
   app.UseCookieAuthentication(new CookieAuthenticationOptions());

   Authority = $"https://login.microsoftonline.com/AAAAA}";
   ClientId = "BBBB";
   ClientSecret = "CCCC";
   Audience = "https://localhost:44333/";

   app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
   {
      ClientId = ClientId,
      Authority = Authority,
      PostLogoutRedirectUri = Audience,
      ResponseType = OpenIdConnectResponseType.CodeIdToken,
      GetClaimsFromUserInfoEndpoint = false,
      Events = new OpenIdConnectEvents
      {
        OnTokenValidated = TokenValidated,
        OnRemoteFailure = OnAuthenticationFailed,
        OnAuthorizationCodeReceived = OnAuthorizationCodeReceived
      }
   });

     app.UseMvc(....);
}
Run Code Online (Sandbox Code Playgroud)

题:

如何配置API以仅使用"Bearer"auth和MVC来使用Cookie?

更新

嗨Adem感谢您的回复.

我从不厌倦第一选择,现在就试试吧.但是我之前已经厌倦了第二个选项,并且只是如下所述累了.

在下面添加了app.UseOpenIdConnectAuthentication(...

app.UseJwtBearerAuthentication(new JwtBearerOptions
{
   Authority = "https://login.microsoftonline.com/AAAA",
   Audience = "https://BBB.onmicrosoft.com/CCCC"
});
Run Code Online (Sandbox Code Playgroud)

对于API控制器 [Authorize(ActiveAuthenticationSchemes = "Bearer")]

对于MVC控制器 [Authorize(ActiveAuthenticationSchemes = "Cookies")]

当它到达我的家庭控制器时,它会收到此错误指定的方法不受支持.

这个堆栈跟踪在Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler 1.HandleSignInAsync(SignInContext context) at Microsoft.AspNetCore.Authentication.AuthenticationHandler1.d__66.MoveNext()---从抛出异常的先前位置的堆栈跟踪结束---在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)at at Microsoft.AspNetCore.Http.Authentication.Internal.DefaultAuthenticationManager.d__14.MoveNext()中的System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)---从抛出异常的上一个位置开始的堆栈跟踪结束---在系统中System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)中的1.<HandleRemoteCallbackAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务),位于Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler 1.d__5.MoveNext()---来自之前的堆栈跟踪结束抛出异常的位置---在System.Runtime.CompilerServices.TaskAwaiter.HandleNo上的System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)处 Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.d__15.MoveNext()中的nSuccessAndDebuggerNotification(任务任务)---从抛出异常的上一个位置的堆栈跟踪结束---在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务)任务)在Microsoft.AspNetCore.Authentication.AuthenticationMiddleware 1.<Invoke>d__18.MoveNext() --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware1.d__18.MoveNext()的System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)---从抛出异常的上一个位置的堆栈跟踪结束---在系统Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.d__6.MoveNext()上的System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)中的.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)

更新2:我已经厌倦了为API和MVC配置2个不同的auth,如下所示

app.UseWhen(context => 
  context.Request.Path.StartsWithSegments("/api"), appBuilder =>
  {
    app.UseJwtBearerAuthentication(new JwtBearerOptions
    {
      Authority = Authority,
      Audience = Configuration["Authentication:AzureAd:Audience"]
    });
  });
app.UseWhen(context => 
  !context.Request.Path.StartsWithSegments("/api"), appBuilder =>
  {
    app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
    {
      ClientId = ClientId,
      Authority = Authority,
      PostLogoutRedirectUri = Audience,
      ResponseType = OpenIdConnectResponseType.CodeIdToken,
      GetClaimsFromUserInfoEndpoint = false,
      Events = new OpenIdConnectEvents
      {
        OnTokenValidated = TokenValidated,
        OnRemoteFailure = OnAuthenticationFailed,
        OnAuthorizationCodeReceived = OnAuthorizationCodeReceived
      }
  });
});
Run Code Online (Sandbox Code Playgroud)

但API似乎仍在使用cookie身份验证.我仍然可以看到请求中包含cookie.

谢谢Asanka

ade*_*lin 5

一种方法是像这样分支应用程序

app.UseWhen(context => <isApiRequest>, appBuilder =>
{
    appBuilder.UseJwtBearerAuthentication(); 
} 
app.UseWhen(context => <isNotApiRequest>, appBuilder =>
{
    appBuilder.UseCookieAuthentication();
} 
Run Code Online (Sandbox Code Playgroud)

注意:你可以用“/api”前缀分支你的api,在这种情况下<isApiRequest>context.Request.Path.StartsWithSegment("/api")

另一种方法是使用AuthenticationScheme

app.UseCookieAuthentication(//....);
app.UseJwtBearerAuthentication(//...);
Run Code Online (Sandbox Code Playgroud)

然后在 api 动作使用Bearer方案中:

[Autho?rize(ActiveAuthenticationSchemes = "Bearer")]
public IActionResult ApiAction(){}
Run Code Online (Sandbox Code Playgroud)

对于 mvc 操作使用Cookies方案

[Autho?rize(ActiveAuthenticationSchemes = "Cookies")]
public IActionResult MvcAction(){}
Run Code Online (Sandbox Code Playgroud)