I am working on a project using ASP .net CORE, where we have Angular 2 and MVC and API, need to be protected by Azure AD.
Home/Index MVC controller will start the Angular 2 SPA and Home/Index need to be protected by cookie authentication. I manage to get the token using the OpenIdConnectAuthentication - OnAuthorizationCodeReceived event.
I need to protect the MVC controllers (there are few more controllers apart from Home/Index) using Cookie based Authentication and API using Bearer Authentication, I can get the token from API to Angular then use that token for each subsequent call to API.
In the near future there will be mobile apps calling the same API end points, using Bearer tokens.
This was my starting point: https://learn.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(....);
}
Question:
How can I configure the API to use just "Bearer" auth and MVC to use Cookies?
Update
Hi Adem Thank you for your reply.
I never tired 1st option, will give it a go now. but I have tired 2nd option earlier, and just tired it as below.
Added this below app.UseOpenIdConnectAuthentication(...
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
Authority = "https://login.microsoftonline.com/AAAA",
Audience = "https://BBB.onmicrosoft.com/CCCC"
});
For API Controller [Authorize(ActiveAuthenticationSchemes = "Bearer")]
For MVC Controller [Authorize(ActiveAuthenticationSchemes = "Cookies")]
When it hits my Home Controller it get this error Specified method is not supported.
this Stack Trace
at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler1.HandleSignInAsync(SignInContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler
1.d__66.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.Http.Authentication.Internal.DefaultAuthenticationManager.d__14.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.RemoteAuthenticationHandler1.<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
1.d__5.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.OpenIdConnect.OpenIdConnectHandler.d__15.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.AuthenticationMiddleware1.<Invoke>d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware
1.d__18.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.Diagnostics.ExceptionHandlerMiddleware.d__6.MoveNext()
Update 2: I have tired configuring 2 different auth for APIand MVC like below
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
}
});
});
But API still seem to be using the cookie auth. I could still see the the request has cookies in the request.
Thank you Asanka
One way is to branch application like this:
app.UseWhen(context => <isApiRequest>, appBuilder =>
{
appBuilder.UseJwtBearerAuthentication();
}
app.UseWhen(context => <isNotApiRequest>, appBuilder =>
{
appBuilder.UseCookieAuthentication();
}
note: you could branch your api with "/api" prefix, in this case <isApiRequest>
would be context.Request.Path.StartsWithSegment("/api")
Another way is to use AuthenticationScheme
:
app.UseCookieAuthentication(//....);
app.UseJwtBearerAuthentication(//...);
Then in api action use Bearer
scheme:
[Authoırize(ActiveAuthenticationSchemes = "Bearer")]
public IActionResult ApiAction(){}
For mvc actions use Cookies
scheme
[Authoırize(ActiveAuthenticationSchemes = "Cookies")]
public IActionResult MvcAction(){}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With