Reputation: 756
I have two asp.net core web applications (using the same application registration id) protected with Azure AD. If I log in to one, the authentication flow breaks for the other, but not the other way around.
I think it has something to do with the authentication cookies and that the Admin app picks upp the one created for the Portal app. If this assumption is correct, how do I make sure the apps don't use each others cookies?
Setup
Test cases
OK : Load Admin and log in
OK : Load Portal and log in
NOK: Load the Portal and log in, navigate to Admin (auth loop)
NOK: Load Admin and log in,
navigate to Portal (credentials not requested, reusing the cookie i guess),
reload Admin (auth loop)
The Admin app reports the following error and creates an authentication redirect loop. Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: Cookies was not authenticated. Failure message: Unprotect ticket failed
Startup.cs for the Portal app
public class Startup
{
public Startup( IConfiguration configuration )
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices( IServiceCollection services )
{
services.AddAuthentication( o =>
{
o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
o.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
}
).AddOpenIdConnect( o =>
{
o.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
o.ClientId = "same-for-both-apps";
o.CallbackPath = "/portal/signin-oidc";
o.Authority = "https://login.windows.net/common";
o.TokenValidationParameters = new TokenValidationParameters
{
RoleClaimType = ClaimTypes.Role,
ValidateIssuer = false,
};
}
).AddCookie( options =>
{ options.AccessDeniedPath = new PathString( "/Account/AccessDenied" ); } );
services.AddMvc( o =>
{
o.Filters.Add( new AuthorizeFilter(
new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build() ) );
}
).SetCompatibilityVersion( CompatibilityVersion.Version_2_2 );
}
public void Configure( IApplicationBuilder app, IHostingEnvironment env )
{
app.MapWhen( IsTargetingPortal, HandlePortalRequest );
app.Run( async ctx =>
{
await ctx.Response.WriteAsync( "Default: info page" );
} );
}
bool IsTargetingPortal( HttpContext ctx )
{
return ctx.Request.Path == "/portal/signin-oidc" ||
ctx.Request.Path == "/portal" ||
ctx.Request.Host.Host.StartsWith( "portal." );
}
void HandlePortalRequest( IApplicationBuilder builder )
{
builder.UseAuthentication();
builder.UseMvc( routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}" );
} );
}
}
Startup.cs for the Admin app
public class Startup
{
public Startup( IConfiguration configuration )
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices( IServiceCollection services )
{
services.AddAuthentication( o =>
{
o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
o.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
}
).AddOpenIdConnect( o =>
{
o.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
o.ClientId = "same-for-both-apps";
o.Authority = "https://login.windows.net/common";
o.TokenValidationParameters = new TokenValidationParameters
{
RoleClaimType = ClaimTypes.Role,
ValidateIssuer = false,
};
}
).AddCookie( options =>
{ options.AccessDeniedPath = new PathString( "/Account/AccessDenied" ); } );
services.AddMvc( o =>
{
o.Filters.Add( new AuthorizeFilter(
new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build() ) );
}
).SetCompatibilityVersion( CompatibilityVersion.Version_2_2 );
}
public void Configure( IApplicationBuilder app, IHostingEnvironment env )
{
app.UsePathBase( "/admin" );
if( env.IsDevelopment() )
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler( "/Error" );
app.UseHsts();
}
app.UseAuthentication();
app.UseMvc();
}
}
Upvotes: 1
Views: 832
Reputation: 756
I solved the cookie mix up by adding
builder.UsePathBase( "/portal" );
to the portal branch of the pipeline
private void HandlePortalRequest( IApplicationBuilder builder )
{
builder.UsePathBase( "/portal" ); // the fix!
builder.UseAuthentication();
builder.UseMvc( routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Portal}/{action=Index}/{id?}" );
} );
}
Upvotes: 0
Reputation: 1066
This would be a matter of registering both apps separately in the Azure AD Portal. This will give you a different client ID. Use the different client ID for each app.
Upvotes: 0