Trying to share auth cookie by following the microsoft docs here: MS Docs
Heres my Startup.vb from the older Webforms project.
<Assembly: OwinStartup("Me", GetType(Startup))>
Public Class Startup
Public Sub Configuration(ByVal app As IAppBuilder)
Dim opt = New CookieAuthenticationOptions
opt.AuthenticationType = "Identity.Application"
opt.CookieName = ".SSO"
opt.LoginPath = New PathString("/Login.aspx")
opt.CookieDomain = "localhost"
opt.CookieHttpOnly = False
opt.CookieSecure = CookieSecureOption.SameAsRequest
Dim proc = DataProtectionProvider.Create(New DirectoryInfo("c:\Temp\DataKeys"), Function(s) s.SetApplicationName("MyApp")).CreateProtector("Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware", "Cookies", "v2")
Dim shim = New DataProtectorShim(proc)
opt.CookieManager = New ChunkingCookieManager()
opt.TicketDataFormat = New AspNetTicketDataFormat(shim)
app.UseCookieAuthentication(opt)
End Sub
End Class
And here is the startup for .net core 3 app.
public class Startup
{
public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
Configuration = configuration;
Environment = env;
}
public IWebHostEnvironment Environment { get; }
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor().AddHubOptions(o =>
{
o.MaximumReceiveMessageSize = 2000 * 1024 * 1024; // 10MB
});
services.AddSingleton<IConfiguration>(Configuration);
services.AddSingleton<IJwtHandler, JwtHandler>();
services.Configure<TokenSettings>(Configuration.GetSection("Token"));
services.AddSingleton<IWebHostEnvironment>(Environment);
services.AddHttpContextAccessor();
services.AddScoped<HttpContextAccessor>();
services.AddFileReaderService();
services.AddTelerikBlazor();
services.AddSweetAlert2();
services.AddSingleton<WeatherForecastService>();
services.Configure<AnimateOptions>(options =>
{
options.Animation = Animations.Fade;
options.Duration = TimeSpan.FromMilliseconds(200);
});
services.AddDataProtection()
.PersistKeysToFileSystem(new System.IO.DirectoryInfo(#"C:\Temp\DataKeys"))
.SetApplicationName("MyApp");
services.AddAuthentication("Identity.Application")
.AddCookie("Identity.Application", options =>
{
options.Cookie = new CookieBuilder
{
Domain = "localhost",
Name = ".SSO",
SameSite = SameSiteMode.Lax,
HttpOnly= false,
SecurePolicy = CookieSecurePolicy.SameAsRequest,
IsEssential = true
};
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
}
I login to the legacy Webforms app, everything works fine. I try to navigate to the .net core 3 app, and it says I'm not authenticated, it does pass the cookie. I'm not sure what I'm doing wrong?
I did end up figuring this out for the most part.
On the .net Core 3 app, you can remove the 'DisableAutomaticKeyGeneration()' call if you plan on generating the keys from the .net core app.
var proc = DataProtectionProvider.Create(new DirectoryInfo(Configuration["SSO:KeyLocation"].ToString()), (builder) => { builder.SetApplicationName("MyApp").ProtectKeysWithDpapi().DisableAutomaticKeyGeneration(); })
.CreateProtector("Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware", "Cookies", "v2");
services.AddAuthentication("Identity.Application")
.AddCookie("Identity.Application", options =>
{
options.TicketDataFormat = new TicketDataFormat(proc);
options.SlidingExpiration = true;
options.Cookie = new CookieBuilder
{
Domain = Configuration["SSO:Domain"].ToString(),
Name = ".SSO",
SecurePolicy = CookieSecurePolicy.None,
IsEssential = true,
};
});
And on the .Net Framework app, You can remove 'ProtectKeysWithDpapi()', if the web apps are not running under the same Service account for the app pools.
Also, you need to make sure you have this version of nuget package installed on both apps,
Microsoft.AspNetCore.DataProtection v3.1.3
Dim opt = New CookieAuthenticationOptions
opt.AuthenticationType = "Identity.Application"
opt.CookieName = ".SSO"
opt.LoginPath = New PathString("/Login.aspx")
opt.CookieDomain = ConfigurationManager.AppSettings("SSODomain")
opt.SlidingExpiration = True
Dim proc = DataProtectionProvider.Create(New DirectoryInfo(ConfigurationManager.AppSettings("SSOKeyLocation")), Function(s) s.SetApplicationName("MyApp").SetDefaultKeyLifetime(TimeSpan.FromDays(9000)).ProtectKeysWithDpapi()).CreateProtector("Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware", "Cookies", "v2")
Dim shim = New DataProtectorShim(proc)
opt.TicketDataFormat = New AspNetTicketDataFormat(shim)
app.UseCookieAuthentication(opt)
For localhost development/testing, just set the domain to 'localhost'
Related
I've just created a new ASP.NET Core application using Visual Studio, it has the authentication type set to "Individual Accounts":
I've added some code to handle OIDC:
builder.Services.AddAuthentication().AddOpenIdConnect(openIdOptions =>
{
openIdOptions.ClientId = "myClientId";
openIdOptions.Authority = "myAuthority";
openIdOptions.ResponseType = OpenIdConnectResponseType.Code;
openIdOptions.GetClaimsFromUserInfoEndpoint = false;
openIdOptions.CallbackPath = "/signin-oidc";
openIdOptions.SaveTokens = true;
Which is all well and good, I can click to login with OpenIdConnect:
When I log in with the provided credentials it pops up asking me to Associate my OpenIdConnect account:
I don't want to have to do this. Retrieving the access token and id token is sufficient for what I want to do, I don't require a local copy of the user. Being new to ASP.net and having not used Razor before it's not immediately obvious what code I should delete — if that's even the correct approach. I've played around with deleting various bits such as the Db setup as I don't really require it, although I suspect Razor does in some regard.
The Program.cs looks as follows:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options =>
{
})
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.AddAuthentication().AddGoogle(googleOptions =>
{
googleOptions.ClientId = builder.Configuration["Authentication:Google:ClientId"];
googleOptions.ClientSecret = builder.Configuration["Authentication:Google:ClientSecret"];
});
builder.Services.AddAuthentication().AddOpenIdConnect(openIdOptions =>
{
openIdOptions.ClientId = "clientId";
openIdOptions.Authority = "authority";
openIdOptions.ResponseType = OpenIdConnectResponseType.Code;
openIdOptions.GetClaimsFromUserInfoEndpoint = false;
openIdOptions.CallbackPath = "/signin-oidc";
openIdOptions.SaveTokens = true;
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.UseEndpoints(endpoints => { endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}"); });
app.Run();
We have a .NET 5 (Blazor Server) app running in Azure Kubernetes that uses OpenID Connect to authenticate with a 3rd party. The app is running behind Ingress. Ingress uses https. The app is only http. After we authenticate with OIDC and get redirected back to /signin-oidc, we get a .NET error that we haven't been able to solve.
warn: Microsoft.AspNetCore.Http.ResponseCookies[1]
The cookie '.AspNetCore.OpenIdConnect.Nonce.CfDJ8EYehvsxFBVNtGDsitGDhE8K9FHQZVQwqqr1YO-zVntEtRgpfb_0cHpxfZp77AdGnS35iGRKYV54DTgx2O6ZO_3gq98pbP_XcbHnJmBDtZg2g5hhPakTrRirxDb-Qab0diaLMFKdmDrNTqGkVmqiGWpQkSxcnmxzVGGE0Cg_l930hk6TYgU0qmkzSO9WS16UBOYiub32GF4I9_qPwIiYlCq5dMTtUJaMxGlo8AdAqknxTzYz4UsrrPBi_RiWUKaF6heQitbOD4V-auHmdXQm4LE' has set 'SameSite=None' and must also set 'Secure'.
warn: Microsoft.AspNetCore.Http.ResponseCookies[1]
The cookie '.AspNetCore.Correlation.MMrYZ2WKyYiV4hMC6bhQbGZozpubcF2tYsKq748YH44' has set 'SameSite=None' and must also set 'Secure'.
warn: Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler[15]
'.AspNetCore.Correlation.MMrYZ2WKyYiV4hMC6bhQbGZozpubcF2tYsKq748YH44' cookie not found.
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
An unhandled exception has occurred while executing the request.
System.Exception: An error was encountered while handling the remote login.
---> System.Exception: Correlation failed.
--- End of inner exception stack trace ---
at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.HandleRequestAsync()
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
public class Startup
{
private static readonly object refreshLock = new object();
private IConfiguration Configuration;
private readonly IWebHostEnvironment Env;
public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
Console.WriteLine($"LogQAApp Version: {Assembly.GetExecutingAssembly().GetName().Version}");
// We apparently need to set a CultureInfo or some of the Razor pages dealing with DateTimes, like LogErrorCountByTime fails with JavaScript errors.
// I wanted to set it to CultureInvariant, but that wouldn't take. Didn't complain, but wouldn't actually set it.
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");
CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("en-US");
Configuration = configuration;
Env = env;
}
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); // Needed for 1252 code page encoding.
Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("");
services.AddSignalR(e =>
{
e.MaximumReceiveMessageSize = 102400000;
});
services.AddBlazoredSessionStorage();
services.AddCors();
services.AddSyncfusionBlazor();
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddHttpContextAccessor();
ServiceConfigurations.LoadFromConfiguration(Configuration);
#region Authentication
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(
options =>
{
options.Events = GetCookieAuthenticationEvents();
}
)
.AddOpenIdConnect("SlbOIDC", options =>
{
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.Authority = Configuration["SlbOIDC:Authority"];
if (Env.IsDevelopment())
{
options.ClientId = Configuration["SlbOIDC:ClientID"];
options.ClientSecret = Configuration["SlbOIDC:ClientSecret"];
}
else
{
options.ClientId = Configuration.GetValue<string>("slbclientid");
options.ClientSecret = Configuration.GetValue<string>("slbclientsecret");
}
options.ResponseType = OpenIdConnectResponseType.Code;
options.UsePkce = true;
options.SaveTokens = true;
options.ClaimsIssuer = "SlbOIDC";
// Azure is communicating to us over http, but we need to tell SLB to respond back to us on https.
options.Events = new OpenIdConnectEvents()
{
OnRedirectToIdentityProvider = context =>
{
Console.WriteLine($"Before: {context.ProtocolMessage.RedirectUri}");
context.ProtocolMessage.RedirectUri = context.ProtocolMessage.RedirectUri.Replace("http://", "https://");
Console.WriteLine($"After: {context.ProtocolMessage.RedirectUri}");
return Task.FromResult(0);
}
};
});
services.AddSession(options =>
{
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.IsEssential = true;
});
#endregion
services.AddScoped<BrowserService>();
services.AddSingleton<ConcurrentSessionStatesSingleton>();
services.AddSingleton<URLConfiguration>();
services.AddScoped<CircuitHandler>((sp) => new CircuitHandlerScoped(sp.GetRequiredService<ConcurrentSessionStatesSingleton>(), sp.GetRequiredService<BrowserService>(), sp.GetRequiredService<IJSRuntime>()));
services.AddScoped<SessionServiceScoped>();
services.AddScoped<LogEditorScoped>();
services.AddSingleton<ModalService>();
services.AddFlexor();
services.AddScoped<ResizeListener>();
services.AddScoped<ApplicationLogSingleton>();
services.AddScoped<LogChartsSingleton>();
services.AddScoped<CurveNameClassificationSingleton>();
services.AddScoped<HubClientSingleton>();
services.AddScoped((sp) => new LogAquisitionScopedService(
sp.GetRequiredService<URLConfiguration>(),
sp.GetRequiredService<HubClientSingleton>(),
sp.GetRequiredService<ApplicationLogSingleton>(),
sp.GetRequiredService<IConfiguration>(),
sp.GetRequiredService<SessionServiceScoped>(),
sp.GetRequiredService<AuthenticationStateProvider>(),
sp.GetRequiredService<IHttpContextAccessor>(),
sp.GetRequiredService<IJSRuntime>()
)
);
services.AddScoped<UnitSingleton>();
services.AddServerSideBlazor().AddCircuitOptions(options => { options.DetailedErrors = true; });
services.AddScoped<TimeZoneService>();
services.AddHostedService<ExcelBackgroundService>();
services.AddHostedService<LogEditorBackgroundService>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
//app.UseHsts();
}
//app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthorization();
app.UseCookiePolicy();
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
app.UseAuthentication();
if (!Env.IsDevelopment())
{
app.UseTrafficManager();
}
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
private CookieAuthenticationEvents GetCookieAuthenticationEvents()
{
return new CookieAuthenticationEvents()
{
OnValidatePrincipal = context =>
{
lock (refreshLock)
{
if (context.Properties.Items.ContainsKey(".Token.expires_at"))
{
DateTime expire = DateTime.Parse(context.Properties.Items[".Token.expires_at"]);
if (expire.AddMinutes(-20) < DateTime.Now)
{
try
{
CloudAuthentication cloudAuthentication = new CloudAuthentication();
TokenResponse tokenResponse = cloudAuthentication.GetRefreshToken(context.Properties.Items[".Token.refresh_token"]);
context.Properties.Items[".Token.access_token"] = tokenResponse.access_token;
context.Properties.Items[".Token.refresh_token"] = tokenResponse.refresh_token;
context.Properties.Items[".Token.expires_at"] = DateTime.Now.AddSeconds(tokenResponse.expires_in).ToString();
context.ShouldRenew = true;
}
catch (Exception ex)
{
context.RejectPrincipal();
}
}
}
return Task.FromResult(0);
}
}
};
}
}
It's a good question - there are a couple of interesting points here that I've expanded on since they are related to SameSite cookies.
REVERSE PROXY SETUP
By default the Microsoft stack requires you to run on HTTPS if using cookies that require an SSL connection. However, you are providing SSL via a Kubernetes ingress, which is a form of reverse proxy.
The Microsoft .Net Core Reverse Proxy Docs may provide a solution. The doc suggests that you can inform the runtime that there is an SSL context, even though you are listening on HTTP:
app.Use((context, next) =>
{
context.Request.Scheme = "https";
return next();
});
I would be surprised if Microsoft did not support your setup, since it is a pretty mainstream hosting option. If this does not work then you can try:
Further searching around Blazor and 'reverse proxy hosting'
Worst case you may have to use SSL inside the cluster for this particular component, as Johan indicates
WIDER INFO - API DRIVEN OAUTH
Many companies want to develop Single Page Apps, but use a website based back end in order to manage the OAuth security. Combining serving of web content with OAuth security adds complexity. It is often not understood that the OAuth SPA security works better if developed in an API driven manner.
The below resources show how the SPA code can be simplified and in this example the API will issue cookies however it is configured. This would enable it to listen over HTTP inside the cluster (if needed) but to also issue secure cookies:
API driven OpenID Connect code
Curity Blog Post
WIDER INFO: SAMESITE COOKIES
It is recommended to use SameSite=strict as the most secure option, rather than SameSite=none. There are sometimes usability problems with the strict option however, which can cause cookies to be dropped after redirects or navigation from email links.
This can result in companies downgrading their web security to a less secure SameSite option. These problems do not occur when an API driven solution is used, and you can then use the strongest SameSite=strict option.
recently we have migrated our project from asp.net to asp.net core, the project was working fine in asp.net, We have followed the migration document of Microsoft for migrating "asp.net to asp.net core" and modified accordingly, unfortunately, OnRedirectToIdentityProvider method in startup class is not working on challenge call (from the controller). It would be great if someone helps me to figure out where my code is wrong. I have been looping on the same issue for a while. thanks in advance.
StartUp.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
//Add a strongly-typed options class to DI
services.Configure<AuthOptions>(Configuration.GetSection("Authentication"));
services.AddAuthentication(opt => {
opt.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
opt.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie("MiddleWareCookie")
.AddOpenIdConnect(options => Configuration.Bind("Authentication", options));
services.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.Authority = Configuration["Authentication:Authority"];
options.ClientId= Configuration["Authentication:ClientId"];
options.ClientSecret= Configuration["Authentication:ClientSecret"];
options.TokenValidationParameters = new TokenValidationParameters
{
// Instead of using the default validation (validating against a single issuer value, as we do in
// line of business apps), we inject our own multitenant validation logic
ValidateIssuer = false,
// If the app is meant to be accessed by entire organizations, add your issuer validation logic here.
//IssuerValidator = (issuer, securityToken, validationParameters) => {
// if (myIssuerValidationLogic(issuer)) return issuer;
//}
};
options.Events = new OpenIdConnectEvents
{
OnRedirectToIdentityProvider = (context) =>
{
object obj = null;
var request = context.Request;
if (context.HttpContext.Items.TryGetValue("Authority", out obj))
{
string authority = obj as string;
if (authority != null)
{
context.ProtocolMessage.IssuerAddress = authority;
}
}
//string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase;
string appBaseUrl = #"https://localhost:44359/";//UriHelper.BuildAbsolute(request.Scheme, request.Host, request.PathBase);
Debug.WriteLine($"appBaseUrl: {appBaseUrl}");
context.ProtocolMessage.PostLogoutRedirectUri = appBaseUrl;
context.ProtocolMessage.Prompt = "select_account";
context.ProtocolMessage.Resource = Configuration["Authentication:AzureResourceManagerIdentifier"];
return Task.FromResult(0);
},
OnAuthorizationCodeReceived = async (context) =>
{
var request = context.HttpContext.Request;
var currentUri = UriHelper.BuildAbsolute(request.Scheme, request.Host, request.PathBase, request.Path);
var credential = new ClientCredential(context.Options.ClientId, context.Options.ClientSecret);
string tenantId = context.Principal.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
//Comment
Debug.WriteLine($"tenantID: {tenantId}");
// Revisit
string signedInUserUniqueName = context.Principal.FindFirst(ClaimTypes.Name).Value.Split('#')[context.Principal.FindFirst(ClaimTypes.Name).Value.Split('#').Length - 1];
//Comment
Debug.WriteLine($"tenantID: {signedInUserUniqueName}");
var tokenCache = new ADALTokenCache(signedInUserUniqueName);
tokenCache.Clear();
// revisit
AuthenticationContext authContext = new AuthenticationContext(string.Format("https://login.microsoftonline.com/{0}", tenantId), tokenCache);
// var items = authContext.TokenCache.ReadItems().ToList();
// revisit
AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(
context.ProtocolMessage.Code, new Uri(currentUri), credential);
//Tell the OIDC middleware we got the tokens, it doesn't need to do anything
context.HandleCodeRedemption(result.AccessToken, result.IdToken);
},
OnTokenValidated = (context) => {
string issuer = context.Principal.FindFirst("iss").Value;
if (issuer != null)
{
if (!issuer.StartsWith("https://sts.windows.net/"))
throw new SecurityTokenValidationException();
}
return Task.FromResult(0);
},
OnTicketReceived = context =>
{
// If your authentication logic is based on users then add your logic here
return Task.CompletedTask;
},
OnAuthenticationFailed = context =>
{
context.Response.Redirect("/Error");
context.HandleResponse(); // Suppress the exception
return Task.CompletedTask;
},
// If your application needs to do authenticate single users, add your user validation below.
//OnTokenValidated = context =>
//{
// return myUserValidationLogic(context.Ticket.Principal);
//}
};
});
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
Subscription Controller Method
HttpContext.Items.Add("Authority", string.Format(_authOptions.Authority + "OAuth2/Authorize", _directoryId));
Dictionary<string, string> dict = new Dictionary<string, string>();
dict["prompt"] = "select_account";
var userIdentity = new ClaimsIdentity(User.Claims, "login");
ClaimsPrincipal principal = new ClaimsPrincipal(userIdentity);
await HttpContext.AuthenticateAsync("MiddleWareCookie");
I can see two things that explain why OnRedirectToIdentityProvider is not called based on your controller code:
you're calling the AuthenticateAsync method where your question states you're calling Challenge;
you're referring to the cookie authentication scheme (MiddleWareCookie), where I think your intent is to trigger an OpenID Connect login.
I believe you need to replace HttpContext.AuthenticateAsync("MiddleWareCookie") with HttpContext.ChallengeAsync() to have the OIDC login request be triggered.
Another potential issue I can see is that you set, in the AddAuthentication method, the DefaultScheme to CookieAuthenticationDefaults.AuthenticationScheme, but the name of your cookie authentication scheme is MiddleWareCookie. These two need to be in sync.
I am starting a new web application, but this time I am using .net core mvc. I have been struggling with all the changes from mvc 5. That said, I was making some great strides when the application stopped running. It compiles error free but when it runs the console does not come up anymore (as it did before) and when the browser opens it just says the site cannot be reached
I don't know what specific code to post as I have no clue where the issue is. It all started when I tried to force HTTPS in the Startup.cs but I have since commented that out and yet it still does not work. Here is Startup.cs in case that helps. How can I get the console back up?
using Bidz4hire;
using Bidz4Hire.Data;
using Bidz4Hire.Models;
using Bidz4Hire.Options;
using Bidz4Hire.Services;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Rewrite;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using System;
using System.IO;
namespace Bidz4Hire
{
public class Startup
{
public Startup(IConfiguration configuration, IHostingEnvironment hostingEnvironment)
{
Configuration = configuration;
// Get the root path on the server [AGD]
GF.RootPath = hostingEnvironment.WebRootPath;
}
public IConfiguration Configuration { get; set; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
//services.Configure<MvcOptions>(options =>
//{
// options.Filters.Add(new RequireHttpsAttribute());
//});
services.AddDbContext<Bidz4HireV1>(options =>
options.UseSqlServer(Configuration.GetConnectionString("Bidz4HireV1")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<Bidz4HireV1>()
.AddDefaultTokenProviders();
services.Configure<IdentityOptions>(options =>
{
// Password settings
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = true;
options.Password.RequireLowercase = true;
options.Password.RequiredUniqueChars = 6;
// Lockout settings
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.AllowedForNewUsers = true;
// User settings
options.User.RequireUniqueEmail = true;
});
services.ConfigureApplicationCookie(options =>
{
// Cookie settings
options.Cookie.HttpOnly = true;
options.Cookie.Expiration = TimeSpan.FromDays(150);
options.LoginPath = "/Account/Login"; // If the LoginPath is not set here, ASP.NET Core will default to /Account/Login
options.LogoutPath = "/Account/Logout"; // If the LogoutPath is not set here, ASP.NET Core will default to /Account/Logout
options.AccessDeniedPath = "/Account/AccessDenied"; // If the AccessDeniedPath is not set here, ASP.NET Core will default to /Account/AccessDenied
options.SlidingExpiration = true;
});
services.AddOptions();
// Add application services.
services.AddTransient<IEmailSender, EmailSender>();
BidzGlobalConfig.appSettings = new BidzSettings();
Configuration.Bind("BidzSettings", BidzGlobalConfig.appSettings);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
//var options = new RewriteOptions()
// .AddRedirectToHttps();
//app.UseRewriter(options);
//app.UseStaticFiles(); //be able to serve files in wwwroot
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), #"Downloads")),
RequestPath = new PathString("/Downloads")
});
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
It would appear that the issue stemmed from the run menu drop-down being set to "IIS Express" instead of my application name. When I set it back to the application name the console pops back up and it runs the application. Core is so different from MVC5 it is really throwing me for a loop.
I have problem with authentication in asp.net Core 2
When I use web browser (that start with visual studio debugging mode )
User.Identity.IsAuthenticated
Worked without problem but when I try to use this API from another domain or Postman (Chrome Extension)
User.Identity.IsAuthenticated
Is always false!
This is my log in code:
var result = await _signInManager.PasswordSignInAsync("user","pass",true,false);
This is my startup.cs
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add database
services.AddDbContext<CoreDbContext>(options =>
{
options.UseSqlServer(ConnectionString);
options.EnableSensitiveDataLogging(true);
}
);
// add sign in manager
services.AddIdentity<User, Role>(options =>
{
// Password settings
options.Password.RequireDigit = false;
options.Password.RequiredLength = 6;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
options.Password.RequireLowercase = false;
// Lockout settings
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
options.Lockout.MaxFailedAccessAttempts = 10;
// User settings
options.User.RequireUniqueEmail = false;
options.SignIn.RequireConfirmedEmail = false;
options.SignIn.RequireConfirmedEmail = false;
})
.AddEntityFrameworkStores<CoreDbContext>()
.AddDefaultTokenProviders();
services.AddCors();
services.AddMvc().AddJsonOptions(options =>
{
options.SerializerSettings.ContractResolver =
new CamelCasePropertyNamesContractResolver();
});
services.Configure<GzipCompressionProviderOptions>(options => options.Level = System.IO.Compression.CompressionLevel.Optimal);
services.AddResponseCompression();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
DbOption.Option = new DbContextOptionsBuilder<CoreDbContext>();
DbOption.Option.UseSqlServer(ConnectionString);
DbOption.Option.EnableSensitiveDataLogging(true);
app.UseResponseCompression();
app.UseCors(builder =>
builder.WithOrigins("http://localhost:4200", "http://192.168.30.100:91", "OtherDomain.com")
.AllowAnyHeader().AllowAnyMethod().AllowCredentials());
app.UseAuthentication();
app.UseMvc();
}
When I use web browser all things work without any problem.
I think this is for cookie proble.