Closed ryhled closed 6 years ago
@javiercn can you help answer this?
@baseless if you can show the stack trace of the exception that would also be helpful. Thanks!
And the startup code you are using
@Eilon the only steps i did was:
Startup code (after i removed AddDefaultUI):
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;
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<IdentityUser, IdentityRole>(options => options.Stores.MaxLengthForKeys = 128)
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
// 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.UseBrowserLink();
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseMvc();
}
}
The raw exception details are:
System.InvalidOperationException: A suitable constructor for type 'Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal.RegisterModel' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.
at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.FindApplicableConstructor(Type instanceType, Type[] argumentTypes, ConstructorInfo& matchingConstructor, Nullable`1[]& parameterMap)
at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateFactory(Type instanceType, Type[] argumentTypes)
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.DefaultPageModelActivatorProvider.CreateActivator(CompiledPageActionDescriptor actionDescriptor)
at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.DefaultPageModelFactoryProvider.CreateModelFactory(CompiledPageActionDescriptor descriptor)
at Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvokerProvider.CreateCacheEntry(ActionInvokerProviderContext context, FilterItem[] cachedFilters)
at Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvokerProvider.OnProvidersExecuting(ActionInvokerProviderContext context)
at Microsoft.AspNetCore.Mvc.Internal.ActionInvokerFactory.CreateInvoker(ActionContext actionContext)
at Microsoft.AspNetCore.Mvc.Internal.MvcAttributeRouteHandler.<>c__DisplayClass12_0.<RouteAsync>b__0(HttpContext c)
at Microsoft.AspNetCore.Builder.RouterMiddleware.<Invoke>d__4.MoveNext()
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.<Invoke>d__6.MoveNext()
at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.<Invoke>d__4.MoveNext()
at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.<Invoke>d__6.MoveNext()
at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.<Invoke>d__6.MoveNext()
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.<Invoke>d__7.MoveNext()
I guess it should be easily reproducable (as long as it isnt caused by something locally on my end). But i can try to fetch whatever you need :).
This is enough to investigate I think. We changed this area substantially on Preview2, so it might not be super relevant. But I'll make sure we look into it.
Thanks for bringing it up.
At a minimum we should have an in-memory E2E test that checks this. Given the churn that we had in the area I'm going to suggest here that we start by adding a test on the new implementation to confirm the behavior.
This doesn't repro in preview2. I've added tests to verify it as part of https://github.com/aspnet/Identity/pull/1749
@javiercn Hi I have same problem but i receive this error on my windows server not in my visual studio is there any thing to update or some component to register or something else ? Thanks
@ekhtiari can you provide a minimal repro project?
@javiercn i find main problem I init new project with identity module ( New default UI for identity). everything is good in visual studio or when i use dotnet run command in project folder but when i publish project i receive this error i try many things like : 1.use this line in view file @model Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal.LoginModel instance @model Loginmodel
i thing when i use this command to generate identity page , something not work correctly : dotnet aspnet-codegenerator identity -dc WebApplication.Data.ApplicationDbContext
i test new init project and publish it and everything was correctly but when i use code generator to create identity page i receive many error about login and register and other thing..
so .. how can i fix this ?
@ekhtiari I don't think I have enough information to help you troubleshoot the issue you're running into. Can you provide a repro project showing the issue?
@javiercn in this repro if you run project in tool folder everything is good and login part and register part is work correctly but if run project in published folder ( bin/Release/PublishOutput/) and use login or register you see my error. identity ui a question : is global tooling cause my problem ? i forgot any thing to install ? i install last version on net core .
I'm running 2.1.0-rc1-final, and I cannot disable the default UI. I have no Areas directory, no Pages directory, and I'm not explicitly calling AddDefaultUI()
in Startup.cs. Still, when I go to a protected action, I get redirected to /Identity/Account/Login
, which actually loads just fine with the default UI. However, I have my own MVC controllers and actions, specific my own sign in action that should be used as the login URL. I even explicitly added the following in Startup.cs:
services.ConfigureApplicationCookie(options =>
{
options.LoginPath = "/signin";
options.LogoutPath = "/signout";
options.AccessDeniedPath = "/signin";
});
This seems to be being entirely ignored, or more likely, overwritten by the default UI's IdentityHostingStartup.cs
.
The default UI should be entirely opt-in. In other words, if you don't add AddDefaultUI()
or actually scaffold it into your project, it should not exist at all. Even better, I think this should be a separate NuGet package, simply to make adding it entirely explicit.
UPDATE
So, I found the problem was in using services.AddDefaultIdentity
. You must use services.AddIdentity
instead, which oddly makes you specify a TRole
type param, when neither AddDefaultIdentity
nor AddIdentityCore
do. Regardless, that solves the problem of the default UI being included, but you still get redirected to /Identity/Accounts/Login
. To fix that, you need to explicitly change the URLs via services.ConfigureApplicationCookie
and make sure that that is after the call to services.AddIdentity
. Then, everything works as it should.
UPDATE 2
So using AddIdentity
led to some exceptions as it still doesn't add all the necessary services apparently. I dug in to what AddDefaultIdentity
is doing and recreated it sans AddDefaultUI
.
services.AddAuthentication(o =>
{
o.DefaultScheme = IdentityConstants.ApplicationScheme;
o.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddIdentityCookies(o => { });
services.AddIdentityCore<ApplicationUser>(o =>
{
o.Stores.MaxLengthForKeys = 128;
})
.AddSignInManager()
.AddDefaultTokenProviders();
services.ConfigureApplicationCookie(o =>
{
o.LoginPath = "/login";
o.LogoutPath = "/logout";
o.AccessDeniedPath = "/access-denied";
});
There should really be an extension method that bootstraps a default Identity setup without the default UI included, and then either just have devs add AddDefaultUI
if they want it, or have an extension method that does the default stuff and that. It's kind of ridiculous that you have to resort to defining all this in your Startup.cs instead of the much more simplistic services.AddDefaultIdentity
, just because you don't want the default UI as well.
but you still get redirected to /Identity/Accounts/Login.
Can you share a small repro project for this? The only time when we update the cookie paths is when you call to AddDefaultIdentity()
@chrisdpratt I've followed your solution above and I've created a new controller for managing the login and logout requests but I'm getting stuck in a redirection loop on the login page.
Startup:
services.AddAuthentication(o =>
{
o.DefaultScheme = IdentityConstants.ApplicationScheme;
o.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddIdentityCookies(o => { });
services.AddIdentityCore<IdentityUser>(o =>
{
o.Stores.MaxLengthForKeys = 128;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddSignInManager()
.AddDefaultTokenProviders();
services.ConfigureApplicationCookie(o =>
{
o.LoginPath = "/Identity/Account/Login";
o.LogoutPath = "/Identity/Account/Logout";
});
services.AddAuthentication().AddGoogle(googleOptions =>
{
var settings = Configuration.GetSection("Google");
googleOptions.ClientId = settings.GetValue<string>("LogInClientId");
googleOptions.ClientSecret = settings.GetValue<string>("LogInClientSecret");
googleOptions.AuthorizationEndpoint += "?hd=domain.com&prompt=select_account";
googleOptions.Events = new OAuthEvents
{
OnCreatingTicket = context =>
{
string domain = context.User.Value<string>("domain");
if (domain != "domain.com")
throw new GoogleAuthenticationException("You must sign in with a domain.com email address");
return Task.CompletedTask;
}
};
});
// MVC
services.AddMvc(options =>
{
if (HostingEnvironment.IsDevelopment())
{
var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
options.Filters.Add(new AuthorizeFilter(policy));
}
else
{
options.Filters.Add(new AllowAnonymousFilter());
}
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
AccountController:
[Area("Identity")]
public class AccountController : Controller
{
[AllowAnonymous]
public async Task Login(string returnUrl = "/")
{
await HttpContext.ChallengeAsync(new AuthenticationProperties() { RedirectUri = returnUrl });
}
public async Task Logout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme, new AuthenticationProperties
{
RedirectUri = Url.Action("Login", "Account", new { area = "Identity" })
});
}
}
Hi there, as @chrisdpratt already mentioned here it would be cool to have a simple without the default UI included. Since all my login UIs are handled via an Angular WebApp the server-side pages are unnecessary.
In this age of "decoupled" services, I am not sure whose brilliant idea it was to tightly couple the core Identity implementation with a "default" UI ! Sorry to be blunt, this is probably among the dumbest ideas I have encountered in a long time. I hope in the next version, sanity prevails & they at least provide a clean way to not include the "default" UI. The default identity template project (in previous versions) with AccountManager implementations etc, worked just fine - yes, we had to do more work to provide our own UI pages for all identity stuff, but that provided excellent flexibility. To couple the core identity implementation along with some "default" (useless) UI (where everything would probably have to be over ridden) into ONE "Razor library" is nothing short of a disaster. I for one am not interested in "scaffolding" on top of your default UI.
@andyfurniss4 I've followed your solution above and I've created a new controller for managing the login and logout requests but I'm getting stuck in a redirection loop on the login page.
I think you may be missing the call to app.UseAuthentication(); (before app.UseMvc , typically in the Configure method) ... the UseAuthentication() call causes the authentication cookie to be passed on requests subsequent to a successful Login, I used the same Services configuration you have suggested and had the same issue till I realized that I was missing the "UseAuthentication" call ..
Hi!
Removing
AddDefaultUI()
(and removing the area) does not seem to clear the default UI.If i remove this from the default template and try to access /Identity/Account/Register i recieve "InvalidOperationException: A suitable constructor for type 'Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal.RegisterModel' could not be located" when i expect to get a 404.
Is this caused by something i missed perhaps or is this an active issue?