I'm trying to build custom cookie authentication in my Blazor Server app.
It works as long as I use the DefaultAuthenticateScheme like this:
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.LoginPath = "/login";
options.LogoutPath = "/logout";
});
Calling HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProperties); will log me.
But I'd like to use custom AuthenticationSchemes to be able to have multiple schemes like:
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie("Attendee", options =>
{
options.LoginPath = "/login";
options.LogoutPath = "/logout";
}).AddCookie("Admin", options =>
{
options.LoginPath = "/admin/login";
options.LogoutPath = "/admin/logout";
});
Calling HttpContext.SignInAsync("Admin", new ClaimsPrincipal(claimsIdentity), authProperties); do set the cookie, but still my app tells me that I'm not authorized.
<AuthorizeView>
<Authorized>Logged in!</Authorized>
<NotAuthorized>NOT logged in!</NotAuthorized> <!-- This is shown -->
</AuthorizeView>
I'd like to be able to control the access with #attribute [Authorize(AuthenticationSchemes = "Admin")] or #attribute [Authorize(Roles = "Admin")] on each component.
What could I be missing?
Your additional cookies aren't being used for authentication.
You could write your own authorization handler/middleware to do that, but by default, I think you can only use one cookie and you set it's name in this line of your code.
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
So, in brief, it's saying you're not authorized because it's testing the scheme CookieAuthenticationDefaults.AuthenticationScheme and not one of your additional two cookies.
Related
I have an ASP.NET Core 6.0 project and I use 2 authentication schemes.
One of the authencation schemes is, as default "JwtBearerDefaults.AuthenticationScheme"
and this works only for Role-based auth.
another one is "Custom"
"Custom" is used only for Policy-based auth.
.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
.....
}
.AddJwtBearer("Custom", options =>
{
.....
});
And after that I added some scopes to "Custom" policy.
I would like to reach the controller with;
[Authorize(AuthenticationSchemes ="Custom",Policy = "RandomPolicyName")]
OR
[Authorize(Roles="User")]
I know I cannot use both on the same controller, it cannot work because it has to pass both authorize attributes. So how can I do that ??
I have developed Identity Server Admin which manages Client and Users and IdentityServer4 which manages Authenticating. both application developed in Asp.Net Core 3.1
Identity Sever Admin is multi tenant application as tenant name in host subdomain.
I have deployed in Azure App Service and used custom domain for both Identity Server Admin(MVC Client) and IdentityServer4
Identity Server Admin - https://tenant1.identityserveradmin.com, https://tenant2.identityserveradmin.com, https://allegion.identityserveradmin.com
IdentityServer4 - https://sts.identityserveradmin.com
in the above domains
tenant1 and tenant2 works perfectly as it get authenticate with Identity server4 and save the cookies but allegion domain doesn't save the cookie and goes into redirect loop
below is my cookie configuration in my startup.cs
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = AuthenticationConsts.OidcAuthenticationScheme;
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultForbidScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignOutScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,
options =>
{
options.Cookie.Name = adminConfiguration.IdentityAdminCookieName;
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.HttpOnly = true;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Events = new CookieAuthenticationEvents
{
OnSignedIn = context => OnSignedIn(context, adminConfiguration, httpContextAccessor),
OnSigningIn = context => OnSigningIn(context, adminConfiguration, httpContextAccessor),
OnValidatePrincipal = context => OnValidatePrincipal(context, adminConfiguration, httpContextAccessor)
};
})
not sure why it's happening weird any help please.
Regards,
Mahendran.
I fixed the issue myself the Client Secret was mismatching and cookies are not validated so this issue happened.
now it got solved
I have the following setup for my application:
services
.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultForbidScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddOpenIdConnect(options =>
{
options.ClientId = Configuration["ClientId"];
options.Authority = $"https://login.microsoftonline.com/{Configuration["TenantId"]}";
options.ClientSecret = Configuration["ClientSecret"];
})
.AddJwtBearer(options =>
{
options.Audience = Configuration["ClientId"];
options.Authority = $"https://login.microsoftonline.com/{Configuration["TenantId"]}";
})
.AddCookie();
services.AddAuthorization();
OIDC and JWT work just fine. Calls from clients using JWT tokens get authenticated. When making browser calls without token user gets redirected to AzureAD auth portal; comes back to the 'signin-oidc' endpoint; OIDC, by using the specified SignInScheme, places the cookie values in the response and gets redirected to the URL that generated challenge.
After redirection I can inspect the Cookies in the request and I can find the .AspNetCore.Cookies values in the request, but no authentication is happening for these requests. They get redirected back to the AzureAD portal for authentication.
Any ideas?
I have 2 devices, pc and a special tablet. I want to have with same app .net core 2.0 2 cookies, or cookies scheme with 2 auth cookies, because for pc I want to expire in 5 minutes and for that special tablet to not expire at all. How to do that. Now I have this...
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "myScheme",
ExpireTimeSpan = TimeSpan.FromSeconds(300),
CookiePath = "/",
CookieSecure = env.IsDevelopment() ? CookieSecurePolicy.SameAsRequest : CookieSecurePolicy.Always
});
I think I could use UseWhen method or I don't know...
Or to sign in on different cookies?
Check Using cookie authentication without ASP.NET Core Identity
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.LoginPath = "/auth";
//https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.cookiebuilder?view=aspnetcore-2.1
options.Cookie = new CookieBuilder
{
Name = "CustomCookie",
HttpOnly = false
};
});
}
public async void Configure(IApplicationBuilder app)
{
app.UseAuthentication();
}
We have need to utilize JWT tokens coming from IdentityServer4 typically, but also from Auth0 for more complex SSO scenarios to authorize access to an asp.net core 2.0 web api.
This code snippet from Startup.cs ConfigureServices tries to register Authentication handlers for both Auth0 and IdentityServer4 processing, but obviously fails with an InvalidOperationException: "Scheme already exists: Bearer"
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Audience = Configuration["Auth0:ApiIdentifier"];
options.Authority = $"https://{Configuration["Auth0:Domain"]}/";
})
.AddIdentityServerAuthentication(options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ApiName = "api1";
});
How can this best be accomplished, I assume involving some type of separate handling based on the issuer in the token?
It turns out that as Muqeet Khan hinted above, the schemes must be named differently, as shown below.
services.AddAuthentication()
.AddJwtBearer("Auth0", options =>
{
options.Audience = Configuration["Auth0:ApiIdentifier"];
options.Authority = $"https://{Configuration["Auth0:Domain"]}/";
})
.AddIdentityServerAuthentication("IdSrv", options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ApiName = "api1";
});
However, the default [Authorize] attribute only calls the default AuthenticationScheme. Rather than specifying both schemes for every Authorization, I registered them globally as so:
services.AddMvcCore()
.AddAuthorization()
.AddJsonFormatters()
.AddMvcOptions(options =>
{
var policy = new AuthorizationPolicyBuilder("IdSrv", "Auth0")
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});