aspnet / aspnetidentity Goto Github PK
View Code? Open in Web Editor NEWASP.NET Identity for ASP.NET 4.x applications
License: Other
ASP.NET Identity for ASP.NET 4.x applications
License: Other
I have created a custom google authenticator token provider implementing IUserTwoFactorTokenProvider. but I'm not sure where and how do I register this new provider in Startup?
public class GoogleAuthenticatorTokenProvider : IUserTwoFactorTokenProvider<User>
{
public GoogleAuthenticatorTokenProvider()
{
}
public Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<User> manager, User user)
{
return Task.FromResult(user.IsGoogleAuthenticatorEnabled);
}
public Task<string> GenerateAsync(string purpose, UserManager<User> manager, User user)
{
return Task.FromResult((string)null);
}
public Task<bool> ValidateAsync(string purpose, string token, UserManager<User> manager, User user)
{
long timeStepMatched = 0;
var otp = new Totp(WebEncoders.Base64UrlDecode(user.GoogleAuthenticatorSecretKey));
bool valid = otp.VerifyTotp(token, out timeStepMatched, new VerificationWindow(2, 2));
return Task.FromResult(valid);
}
}
aspnet/AspNetKatana#331 (comment)
UseExternalSignInCookie creates a temp cookie for remote auth signin (e.g. Facebook). However it only lets you configure the name. If you want to make changes then you need to copy the code into your project (very confusing for users).
This has become more relevant since there was a .NET patch that interferes with this cookie. Users need to set the SystemWebCookieManager to mitigate the issue.
Proposal:
public static void UseExternalSignInCookie(this IAppBuilder app, Action<CookieAuthenticationOptions> configure)
public static void UseExternalSignInCookie(this IAppBuilder app, string externalAuthenticationType, Action<CookieAuthenticationOptions> configure)
I'm using Asp.Net Identity on .Net Framework 4.8 and MVC 5. I'm using HttpContext to track contextual information about a request. However Asp.Net Identity uses ConfigureAwait(false)
, which means that HttpContext.Current
becomes null
in callbacks. For example when subclassing PortalSignInManager
, HttpContext.Current
is null
inside SignInAsync
.
I suppose WithCurrentCulture
was introduced when Asp.Net Core didn't flow HttpContext
. However that's no longer the case for newer versions, and this workaround is breaking my application.
ChangeEmailAsync
is not updating the username though I have set the uniqueEmailAddress in the builder.
var builder = services.AddIdentity<ApplicationUser, ApplicationRole>(opt => { opt.User.RequireUniqueEmail = true; }
one of the issues have "IsUsernameEmailAddress" dynamic property added recently. I'm using 2.1 .net core. but could not see this.
Wondering do I need to use the above in this case? or Is it a bug?
Ex: Generate token GenerateChangeEmailTokenAsync
then ChangeEmailAsync
to see the behaviour.
It is possible to use the second factor code more than once, e.g. when using the EmailTokenProvider. For security, I would expect that the second factor code becomes invalid after a successful login.
To reproduce:
A possible workaround is to call UserManager.UpdateSecurityStampAsync(userId)
after a successful two factor authentication. This will invalidate all issued second factor codes for the user.
I need to reuse Identity 3.0 (.Net Core) users to Identity 2.2.1 (.Net Framework) but login is failing because the password is not matching. help, please.
Is there a difference in the Hashing mechanism in .Net Core vs .Net Framework?
Identity 3.0 sample password looks like AQAAAAEAACcQAAAAExxxxxxxx.
Setting up roles seems to be a lot harder than I think it should be. Using code first, it appears the tables related to roles were created. But understanding how to enable and populate them is frustrating.
I've found numerous articles explaining how to do it and everyone of them is different. None of the Microsoft articles seems specific to this.
Based on what I've read, I end up with something like this in startup.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<ApplicationUser>(options =>
{
options.SignIn.RequireConfirmedAccount = false;
})
.AddRoles<ApplicationUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddRazorPages();
// Set the default authentication policy to require users to be authenticated
services.AddControllers(config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
});
}
But the call to AddDefaultIdentity
raises an exception.
System.InvalidOperationException: 'AddEntityFrameworkStores can only be called with a role that derives from IdentityRole.'
I just want to enable roles and prepopulate the roles with the ones I'm using. Is there no straight forward way documented to do this?
Reported by a user on nuget.org:
The file version of this library (Microsoft.AspNet.Identity.Core.dll, also Microsoft.AspNet.Identity.EntityFramework.dll and Microsoft.AspNet.Identity.Owin.dll) is set to 0.0.0.0 causing problems during update installations.
The problem might originate from the internal version number being 2.2.2.70424.0, with the fourth component being larger than 65535.
Can you rerelease this package with fixed version numbers?
Here is the info for 2.2.2 of Microsoft.AspNet.Identity.Core.dll
From @rvandulek on November 12, 2017 22:41
I'm in the process of creating a new MVC application that has to plug in to our existing SQL Server based user store. The problem is old user accounts can't be used in the new website, trying to log in with one results in "failure". New accounts can be created, but can't be used by the existing MVC web sites, try to login in with one results in "failure". I'm guessing this is a compatibility issue for the hashed passwords. How can I configure the new site, to use the existing (circa 2014 MVC) password hash? I've compared the NuGet packages in both websites and they match (both are using 2.2.1)
Copied from original issue: aspnet/Identity#1501
If Email field is null or empty the UserManager will not update the database table and since AccessFailedCount is stored in the same table it will not be incremented.
await UserManager.AccessFailedAsync(user.Id).WithCurrentCulture();
returns an error, but this is not checked, in SignInManager.PasswordSignInAsync
and SignInManager.TwoFactorSignInAsync
.
This means that an attacker can guess passwords for such a user indefinitely.
Hi, i'm trying to change the expiration time of the EmailConfirmationToken that is generated with the GenerateEmailConfirmationTokenAsync method.
To do that, i added the next code in startup.cs class:
private const string EmailConfirmationTokenProviderName = "ConfirmEmail";
public void ConfigureServices(IServiceCollection services)
{
...
services.Configure<IdentityOptions>(options =>
{
options.Tokens.EmailConfirmationTokenProvider = EmailConfirmationTokenProviderName;
});
services.Configure<ConfirmEmailDataProtectionTokenProviderOptions>(options =>
{
options.TokenLifespan = TimeSpan.FromDays(1);
});
services.AddIdentity<ApplicationUser, IdentityRole>(
item =>
{
...
item.Tokens.EmailConfirmationTokenProvider = EmailConfirmationTokenProviderName;
item.Tokens.PasswordResetTokenProvider = EmailConfirmationTokenProviderName;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders()
.AddTokenProvider<ConfirmEmailDataProtectorTokenProvider<ApplicationUser>>(EmailConfirmationTokenProviderName);
...
}
public class ConfirmEmailDataProtectionTokenProviderOptions : DataProtectionTokenProviderOptions { }
public class ConfirmEmailDataProtectorTokenProvider : DataProtectorTokenProvider where TUser : class
{
public ConfirmEmailDataProtectorTokenProvider(IDataProtectionProvider dataProtectionProvider, IOptions options, ILogger logger) : base(dataProtectionProvider, options, logger)
{
}
}
The project is in Core 3.1, when i set options.TokenLifespan = TimeSpan.FromMinutes(5) for example, it works perfectly but when i set 24 hours or one day in TokenLifespan, the token expire in one hour more or less. The same problem occurs with PasswordResetToken.
Can't exceed a max time? How could I solve the problem?
There is no apparent/obvious way to configure the lifetime of a 2-factor token; in the case where email delivery is delayed, the token may already be expired when reaching the recipient.
Result:
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HMCIB3PQJ72M", Request id "0HMCIB3PQJ72M:00000002": An unhandled exception was thrown by the application.
System.FormatException: String '' was not recognized as a valid DateTime.
at System.DateTimeParse.Parse(ReadOnlySpan`1 s, DateTimeFormatInfo dtfi, DateTimeStyles styles, TimeSpan& offset)
at System.DateTimeOffset.Parse(String input, IFormatProvider formatProvider, DateTimeStyles styles)
at System.DateTimeOffset.Parse(String input, IFormatProvider formatProvider)
at Microsoft.Data.Sqlite.SqliteValueReader.GetDateTimeOffset(Int32 ordinal)
at Microsoft.Data.Sqlite.SqliteValueReader.GetFieldValue[T](Int32 ordinal)
at Microsoft.Data.Sqlite.SqliteDataRecord.GetFieldValue[T](Int32 ordinal)
at Microsoft.Data.Sqlite.SqliteDataReader.GetFieldValue[T](Int32 ordinal)
at lambda_method104(Closure , QueryContext , DbDataReader , ResultContext , SingleQueryResultCoordinator )
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Identity.UserManager`1.FindByNameAsync(String userName)
at Microsoft.AspNetCore.Identity.SignInManager`1.PasswordSignInAsync(String userName, String password, Boolean isPersistent, Boolean lockoutOnFailure)
at BioMindsXRSrv.Web.Controllers.UserController.Login(String userName, String password) in D:\GitHub\BioMindsXR_Srv\BioMindsXRSrv.Web\Controllers\UserController.cs:line 78
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
Code for login:
var addInfo = string.Empty;
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
{
[78line] var result = await signInManager.PasswordSignInAsync(userName, password, false, false);
addInfo = result.ToString();
if (result.Succeeded)
{
return Redirect("~/");
}
}
user:
public class User : IdentityUser<Guid>
{
[DisallowNull]
[Required]
[PersonalData]
public string FirstName { get; set; } = string.Empty;
[DisallowNull]
[Required]
[PersonalData]
public string LastName { get; set; } = string.Empty;
[PersonalData]
public UserSettings UserSettings { get; set; } = new UserSettings();
[PersonalData]
public ICollection<UserTherapy>? UserQuests { get; set; }
[PersonalData]
public bool IsAdmin { get; set; }
[PersonalData]
public bool IsDoctor { get; set; }
[PersonalData]
public Guid? DoctorId { get; set; }
[NotMapped]
public IEnumerable<string> RoleNames { get; set; }
[IgnoreDataMember, NotMapped]
public string Password { get; set; }
[IgnoreDataMember, NotMapped]
public string ConfirmPassword { get; set; }
[IgnoreDataMember, NotMapped]
public string Name
{
get => UserName;
set => UserName = value;
}
[PersonalData]
public string? HospitalName
{
get;
set;
}
[PersonalData]
public string? Phone
{
get;
set;
}
[PersonalData]
public DateTime? DateOfTheTest { get; set; }
[PersonalData]
public string? Diagnosis { get; set; }
[PersonalData]
public DateTime? DateOfDiagnosis { get; set; }
[PersonalData]
public DateTime? StartDateOfTherapy { get; set; }
[PersonalData]
public EHandiness? Handiness { get; set; }
[PersonalData]
public string? AdlScores { get; set; }
[PersonalData]
public string? BarthelResults { get; set; }
[PersonalData]
public string? NeuropsychologicalResults { get; set; }
[PersonalData]
public string? Other { get; set; }
}
Could you please change the ConvertIdFromString method to return using this code in the Microsoft.AspNetIdentity.Owin.SignInManager class:
return (TKey)TypeDescriptor.GetConverter(typeof(TKey)).ConvertFromInvariantString(id);
I downloaded the source code, made this change on my local. However, when I try to run my project with this new update I get an error about StrongName verification.
I've created extension method that allow me to verify if token has expired.
Code is available here: aspnet/Identity#307 (comment)
I'd like to ask for changing protection level of StreamExtensions to public, because right now I must copy same code to my extension method.
I've created question on SO about any security vulnerabilities of my code , so any comments are more than welcome
When adding multiple roles or generally updating a user's roles, I'd like to be able to just give UserManager.AddToRolesAsync()
the full list of roles that the user should have and have it add any new roles. As it currently is, if the user already has even 1 of the roles being assigned, the operation reports as a failure, at best having added any new roles in the list prior to the role that the user already has.
Similarly, when removing roles, UserManager.RemoveFromRolesAsync()
will fail if the user does not have any of the given roles when, in my opinion, it should ignore those and continue with removing any that the user does have.
Looking at the code, it appears that it could be as simple as changing return new IdentityResult(Resources.UserAlreadyInRole);
to continue;
in UserManager.AddToRolesAsync()
and changing return new IdentityResult(Resources.UserNotInRole);
to continue;
in UserManager.RemoveFromRolesAsync()
.
The AllowOnlyAlphanumericUserNames
option is supposed to only allow usernames that are made up of letters or digits. However, as you can see in the regex check here, it still allows usernames with @
, _
, or .
.
Hello!
using the command userManager.GenerateTwoFactorTokenAsync () I create a new TwoFactorToken. How to delete an old token? so that when you try to enter the old token, the system gives an error
I want to localize ASP.NET Identity error messages.
Where is "Microsoft.AspNet.Identity.Core.zh-Hans" latest version(v3.1.6)
Hi,
After I scaffolded ASP.NET Core Identity into my Blazor (Server) project I noticed that I was unable to change email address using the function presented on Account\Manage\Email.cshtml
The email confirmation would send as expected however when I clicked on the link the value of result.Succeeded on line 42 of Account\ConfirmEmailChange.cshtml.cs was always false.
code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code));
var result = await _userManager.ChangeEmailAsync(user, email, code);
if (!result.Succeeded)
{
StatusMessage = "Error changing email.";
return Page();
}
In noticed on Account\Manage\Email.cshtml.cs that within OnPostSendVerificationEmailAsync() after the token code was generated on line 129 using await _userManager.GenerateEmailConfirmationTokenAsync(user)
that it was then encoded using code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
This encoding is missing within OnPostChangeEmailAsync() after var code = await _userManager.GenerateChangeEmailTokenAsync(user, Input.NewEmail);
on line 93.
When I add code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
to line 94 the issue is resolved and result.Succeeded returns true.
Thanks
Various places in the SignInManager
compare the userId
against null
. This is a problem for value types, for example Guid
. I cannot use Guid?
in my TUser
as it needs to implement IEquatable<TKey>
.
public override Guid ConvertIdFromString(string id) => Guid.Parse(id);
This returns Guid.Empty
if id == null
. However Guid.Empty != null
and various places now assume a valid user. I see two possible fixes for this:
TKey
to be a reference type: null
checks can remain as-is.null
checks with default
checks: Guid.Empty == default
.Some places where using a value type is a problem:
Hi,
I'm having a weird issue and this is the last place to search for an answer. I have created a site for deployment to my ISP. Whenever I try to sign in with users created locally it returns Result.Failed. I'm using the generic Identity scaffold with Personal Data added.
I have deployed another site to the same ISP with the same boiler plate code and it worked fine. I found the error by returning result.ToString() in the else statement in Login.cshtml.cs as the PasswordSighInAsync function only returns a status message and not an error.
else
{
ModelState.AddModelError(string.Empty, result.ToString());
return Page();
}
I checked the SigninManager code here and there are three situations when failure is assigned, but it's not clear why logging into the same remote DB with the same ApplicationDbContext succeeds when I run locally in either debug or release.
I also hit the error below when trying to register from the .com web site and it doesn't happen locally. But checking the DB the user is created. Testing also showed that setting RequireConfirmedAccount to false still returns NotAllowed.
Turning off the RequireConfirmed was necessary becuase the GenerateTokenAsync() call would fail
**Error.
An error occurred while processing your request.
Request ID: 00-825112947d1a57ef4eca465146ff6805-747b92bafdb872df-00
Development Mode
Swapping to Development environment will display more detailed information about the error that occurred.
The Development environment shouldn't be enabled for deployed applications. It can result in displaying sensitive information from exceptions to end users. For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development and restarting the app.**
Hi,
I would like to know if it is possible to extend IdentityUserClaim.
So far I've created a CustomIdentityUser and CustomIdentityUserClaim. Next I've added a Claims property for CustomIdentityUserClaim using the new keyword (override not possible because of different type) to the CustomerIdentityUser.
The database is created without any troubles using EF. However when trying to use the database, e.g. using for CustomUserManager.FindAsync an exception is thrown stating "The navigation property 'Claims' on entity type 'CustomIdentityUser' cannot be used for entities of type 'IdentityUserClaim' because it refers to entities of type 'CustomIdentityUserClaim'."
I've already tried inheriting from IdentityUser<>, however this results in problems with using the UserStore as this expects IdentityUser.
Any thoughts or ideas?
Cheers,
Peter
Similarly to the SameSite extension a few years ago, Google is planning to imminently change the default handling of third party cookies in Chrome (see https://developers.google.com/privacy-sandbox/3pcd/chips for more information). In many use cases and scenarios involving framing a widget or similar in an external site, this will be required for third party cookies to continue to work on Chrome (for non-tracking purposes). They plan to enable this for 1% of users imminently. We still have some applications on .NET 4.x using ASPNetIdentity and this support is fairly crucial for some of our embedding scenarios where our site is embedded in a third party site (not for advertising, but for functionality). We need support for adding the "Partitioned" attribute to auth cookies to allow them to continue to be set in these use cases.
It appears that this has been addressed in the Core Identity library, but not the 4.x version: dotnet/aspnetcore#39968
I'd propose that a new CookiePartitioned
property be added to the CookieAuthenticationOptions
class, and then used to send this attribute if true.
If there is some workaround to allow setting this additional attribute without adding an explicit property, I'd be open to hearing about it.
Hello,
on nuget we can find the language files for many languages, like Microsoft.AspNet.Identity.Core.es for Spanish, for example. But we need language file for Dutch now and we can't find the one. Do we search wrong way?
It is not problem for us to include these labels to be translated, as we translate rest of our app to Dutch, but we can't find repo or source code for other languages, so we do not know where to submit these translations eventually.
Can you help us with it?
Thanks, Tom
I'm trying to migrate parts of my application to .net core instead of everything at once. I'd like to try moving from EF to EF Core now but can't because of ASP.NET Identity relying it. Are there any EF Core storage providers for ASP.NET Identity? I haven't had much luck searching for one because of the similar names.
The UserManager.UpdatePassword method's name does not end in 'Async' but returns a Task. It should be named (as all other Task based methods in the class) UpdatePasswordAsync.
Need to copy all the codes and branches from http://aspnetidentity.codeplex.com/ and import to here. CodePlex is shutting down very soon so we need to do this ASAP.
I went through a guide describing how to configure navigation properties for the identity package and encounter a problem with relations between defined navigation properties, causing problem with eg. assinging role to user.
Steps to reproduce:
UserRoles
link to source.UserManager<ApplicationUser>
with method CreateAsync
.RoleManager<ApplicationRole>
with method CreateAsync
.UserManager<ApplicationUser>
with method AddToRoleAsync
.UserRole
table which is correct, but with incorrect UserId
and RoleId
, which does not exist and was generated with running previous step.I checked assigning role to user directly using ApplicationDbContext
, which was successful and no ghost entries were added to Users
and Roles
tables:
context.UserRoles.Add(new ApplicationUserRole
{
RoleId = adminRole.Id,
Role = adminRole,
UserId = admin.Id,
User = admin,
});
The same situation happens when using other navigation properties like IdentityClaims
and etc.
Issue reproduced with:
Using 2.2.1 but can see the issue in master
PasswordSignInAsync will reset it for non-2FA accounts:
TwoFactorSignInAsync will reset it for 2FA accounts:
But if the user has previously remembered the browser, TwoFactorSignInAsync never happens, so it never resets.
Now that I understand what is going on, we can address it by resetting as appropriate, but this behavior was not expected and leaves 2FA accounts that have been locked out before in a state such that any single successive password failure after the lockout has expired, will increment the count (which is still over the limit) and locks the account again.
Some thoughts on possibilities:
Hi,
I've been trying to persist a custom claim in the browser on sign-in and it feels like there's a bit of a conflict with how subsequent requests are handled, but maybe I'm missing something obvious.
The claims exist in the cookie, and are successfully restored to the ClaimsPrincipal
via CookieAuthenticationHandler
, but then somewhere further along the pipeline, the UserClaimsPrincipalFactory
comes along and decides what the claims should be for the user - and obviously they don't include my custom one(s).
In the past I've dealt with this by subclassing UserClaimsPrincipalFactory
and doing a database lookup for the extra claims I need, but in this case I don't want to, as the claim is specific to the browser that the user signed in with - not their account/identity. If they're signed out I'm perfectly happy to lose this claim as it'll be regenerated when they sign in again. It's also really useful to have that information as just another claim, as I can easily pick it up from filters, etc.
Am I doing something wrong? Is there a way to bring these two concepts together in some kind of harmony? At the moment it seems like cookie claims are pretty much irrelevant.
Thanks in advance for any pointers.
Nat
I am trying to add a shadow property to all my tables using the following code in my builder override,
foreach (var entityType in builder.Model.GetEntityTypes ()) {
entityType.GetOrAddProperty ("IsDeleted", typeof (bool));
var parameter = Expression.Parameter (entityType.ClrType);
var propertyMethodInfo = typeof (EF).GetMethod ("Property").MakeGenericMethod (typeof (bool));
var isDeletedProperty = Expression.Call (propertyMethodInfo, parameter, Expression.Constant ("IsDeleted"));
BinaryExpression compareExpression = Expression.MakeBinary (ExpressionType.Equal, isDeletedProperty, Expression.Constant (false));
var lambda = Expression.Lambda (compareExpression, parameter);
builder.Entity (entityType.ClrType).HasQueryFilter (lambda);
}
I have This "ApplicationRole" class which extends the IdentityRole,
public class ApplicationRole : IdentityRole {
public string Description { get; set; }
[Required]
public Guid DatabaseId { get; set; }
[ForeignKey ("DatabaseId")]
public virtual PracticeDatabase Database { get; set; }
}
How can I resolve this conflict?
currently I resolve it by exlcuding the extended class as follows,
if (entityType.Name == "ArtNgCore.Core.Models.IdentityModels.ApplicationRole") {
return;
}
is there another way ?
The conflict message is,
System.InvalidOperationException: The property or navigation 'IsDeleted' cannot be added to the entity type 'IdentityRole' because a property or navigation with the same name already exists on entity type 'ApplicationRole'.
at Microsoft.EntityFrameworkCore.Metadata.Internal.EntityType.AddProperty(String name, Type propertyType, MemberInfo memberInfo, ConfigurationSource configurationSource, Nullable1 typeConfigurationSource) at Microsoft.EntityFrameworkCore.Metadata.Internal.EntityType.AddProperty(String name, Type propertyType, ConfigurationSource configurationSource, Nullable
1 typeConfigurationSource)
at ArtNgCore.Persistence.Core.ArtCoreDbContext.OnModelCreating(ModelBuilder builder) in /Users/json/OneDrive/MyProjects/ArtNgCore/Persistence/Core/ArtCoreDbContext.cs:line 68
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder, IModelValidator validator)
at System.Lazy1.ViaFactory(LazyThreadSafetyMode mode) at System.Lazy
1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
at System.Lazy1.CreateValue() at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel() at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model() at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies() at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider() at Microsoft.EntityFrameworkCore.Internal.InternalAccessorExtensions.GetService[TService](IInfrastructure
1 accessor)
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func1 factory) at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType) at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType) at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType) at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0
1.b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
The property or navigation 'IsDeleted' cannot be added to the entity type 'IdentityRole' because a property or navigation with the same name already exists on entity type 'ApplicationRole'
It seems like there is something wrong with Microsoft.AspNetCore.Authentication.JwtBearer library. I made an API that uses this library. it works perfect in dev.
But when I publish in production (Release, Self-Contained, win-x64) , I am getting error indicating Newtonsoft.json version 10.0 not found (and further complaining about not able to get config from my IdentityServer).
My debug folder has version 10.0.1, but my publish folder has version 9.0.1 !
The error goes away when I manually replace the NewtonSoft.json with the one in my debug folder.
I am using
.NetCore 3.1.
Microsoft.AspNetCore.Authentication.JwtBearer 3.1.7
I'm wondering if there's a reason why the file version field for 2.2.2 hasn't been set for the Owin, EntityFramework and Core assemblies? For 2.2.1 the file version field was set to 2.2.1.40403 but in the latest version it's just set to 0.0.0.0.
This is causing us issues when we try to update the assemblies with a Windows Installer because it thinks that 2.2.2 is older than 2.2.1 since the file version fields are set to zero. So we are seeing errors like this for the Identity components:
MSI (c) (84:54) [16:21:44:440]: Disallowing installation of component: {49CB1C30-1258-4AB8-951C-D580FCAFD9F8} since the same component with higher versioned keyfile exists
I found this StackOverflow answer from Rob Mensching explaining the problem in greater detail: https://stackoverflow.com/a/15139855/253193
I'd like to disable AutoSaveChanges (I also changed key type to int), then create user, add it to role and save it to database. CreateAsync is succcessful. However when I try to add user to role I'm getting following error:
{
"error": "The property 'User.Id' has a temporary value while attempting to change the entity's state to 'Unchanged'. Either set a permanent value explicitly, or ensure that the database is configured to generate values for this property."
}
AutoSaveChanges
UserManager::CreateAsync
UserManager::AddToRoleAsync
Actual result:
Error occurs:
{
"error": "The property 'User.Id' has a temporary value while attempting to change the entity's state to 'Unchanged'. Either set a permanent value explicitly, or ensure that the database is configured to generate values for this property."
}
Expected result:
User added to role
Yes. Looking at the identity code I noticed that internally UpdateAsync
is called after AddToRoleAsync
. UpdateAsync
calls Context.Attach
on the user object. However user object is already tracked and modified so that the exception is thrown. I changed UpdateAsync
in my custom user store to:
public override async Task<IdentityResult> UpdateAsync(User user, CancellationToken cancellationToken = default)
{
if (AutoSaveChanges)
{
return await base.UpdateAsync(user, cancellationToken);
}
return IdentityResult.Success;
}
but then different error occurred:
{
"error": "The value of 'UserRole.UserId' is unknown when attempting to save changes. This is because the property is also part of a foreign key for which the principal entity in the relationship is not known."
}
Looking at DebugView.LongView
I noticed that UserId
in UserRole
is different than Id
in User
so that relationship is wrong:
User {Id: -2147482647} Added
Id: -2147482647 PK Temporary
AccessFailedCount: 0
...
UserRole {UserId: -2147482646, RoleId: 1} Added
UserId: -2147482646 PK FK Temporary Unknown
RoleId: 1 PK FK
...
Id
which is set on User
entity is 0 but Id
tracked by EF is -2147482647. It seems that store does not recognize that Id
has temporary value and treats it as new one. To "fix" relationship I assigned UserId
in custom store:
protected override UserRole CreateUserRole(User user, Role role)
{
var currentValueId = Context.Entry(user).Property(e => e.Id).CurrentValue;
user.Id = currentValueId;
return base.CreateUserRole(user, role);
}
Now it's working without exceptions. However it seems that it should be handled correctly by Identity. It seems that UpdateAsync
is not needed to be called if AutoSaveChanges
is false as the caller already decided to do it by himself. Entity should be also recognized as temporary.
Hello,
I have problem with Identity remote (in hosting),
the queries (list of products etc) to the database works, except the queries with Identity (Authentication)
Here is my connection chain:
And this is example for connection string from MS SQL Ionos:
Provider=sqloledb;Data Source=db******.hosting-data.io,1433;Initial Catalog=db*******;User Id=dbo******;Password=*****;
Stack Trace : https://pastebin.com/zjTyir6r
If you set an explicit LoginPath for CookieAuthenticationOptions, authenticated users who navigate a restricted area they are not authorized to access (e.g. because of not having the right role), will trap in a redirect loop.
Steps to produce the issue
[Authorize] filter in MainController sends the user to the login page (LoginPath) together with a ReturnUrl. There, CookieAuthentication middleware detects that current user is an authenticated user and there is also a ReturnUrl param in the Url, so, it redirects the user back to the ReturnUrl.
The surprising thing is that the Login() action in AccountController -AccountController.Login(string returnUrl) - is also executed each time the user is redirected to login page!
This issue does not happen if you do not set an explicit LoginPath for CookieAuthentication middleware. In this case, when an authenticated user is redirected from a restricted area to login page (with a ReturnUrl param), the View in login page is executed normally and returned. So, we can check Request.IsAuthenticated in the View and instead of the login form show a message such as "You are currently logged in as ...., click here to sign in as another user".
This is the same thing I wanted to do in my own project, but since I had set a LoginPath, I was facing the "too many redirects" error. It took me a half day until I found out the culprit is CookieAuthenticationOptions.LoginPath!
hi @HaoK
Queries for usernames and email addresses in UserStore and RoleStore are converted to uppercase.
AspNetIdentity/src/Microsoft.AspNet.Identity.EntityFramework/UserStore.cs
Lines 400 to 404 in a24b776
Consider this situation:
Thread.CurrentThread.CurrentCulture = new CultureInfo("tr");
var admin = await _userManager.FindByNameAsync("admin");
In the current culture, the uppercase of admin is no longer ADMIN but ADMİN
This will cause problems.
I saw the latest IdentityCore added NormalizedUserName
and converted using ToUpperInvariant
.
How to deal with the problems caused by this cultural difference?
thanks.
Anytime I call userManager. AccessFailedAsync
the database is never updated and the code never fails. When I attempt to debug the code using the downloaded symbols, I am not able to set breakpoints on every line and the code jumps out unexpectely
var result = await userManager.AccessFailedAsync(user);
A search of StackOverflow reveals others having the same problem
https://stackoverflow.com/questions/54460611/user-manager-accessfailed-async-not-incrementing
On 3/19/2021 we're going to rename the default branch in this repository to main. For more details, see our earlier announcement.
I just wonder, is there a special reason why you don't use MemoryStream in using blocks?
On the other hand, it's used in a using block in this code:
https://github.com/aspnet/Mvc/blob/00c6b53b062e7996c85873754c3b79f50db67ee1/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/TempDataSerializer.cs#L50
I am trying to use userManager.CreateIdentityAsync method, but I get a NRE everytime.
After debugging the code for AspNetIdentity, I have noticed that the NRE was thrown when calling CreateAsync in ClaimsIdentityFactory class method.
More precisely, the exception is thrown when iterating over the list of roles, but in my particular case it is null
and so it throws. I have added a comment in the code to indicate exactly where the exception is thrown:
/// <summary>
/// Create a ClaimsIdentity from a user
/// </summary>
/// <param name="manager"></param>
/// <param name="user"></param>
/// <param name="authenticationType"></param>
/// <returns></returns>
public virtual async Task<ClaimsIdentity> CreateAsync(UserManager<TUser, TKey> manager, TUser user,
string authenticationType)
{
if (manager == null)
{
throw new ArgumentNullException("manager");
}
if (user == null)
{
throw new ArgumentNullException("user");
}
var id = new ClaimsIdentity(authenticationType, UserNameClaimType, RoleClaimType);
id.AddClaim(new Claim(UserIdClaimType, ConvertIdToString(user.Id), ClaimValueTypes.String));
id.AddClaim(new Claim(UserNameClaimType, user.UserName, ClaimValueTypes.String));
id.AddClaim(new Claim(IdentityProviderClaimType, DefaultIdentityProviderClaimValue, ClaimValueTypes.String));
if (manager.SupportsUserSecurityStamp)
{
id.AddClaim(new Claim(SecurityStampClaimType,
await manager.GetSecurityStampAsync(user.Id).WithCurrentCulture()));
}
if (manager.SupportsUserRole)
{
IList<string> roles = await manager.GetRolesAsync(user.Id).WithCurrentCulture(); // <-- roles is null
foreach (string roleName in roles) // <-- NRE thrown here
{
id.AddClaim(new Claim(RoleClaimType, roleName, ClaimValueTypes.String));
}
}
if (manager.SupportsUserClaim)
{
id.AddClaims(await manager.GetClaimsAsync(user.Id).WithCurrentCulture());
}
return id;
}
I am not sure why the list of roles is null
though. Is this bug or is there something I am missing there? Thanks.
NuGet:
I'm implementing TOTP using the TotpSecurityStampBasedTokenProvider and couldn't figure out why it wasn't working with Google Authenticator.
While debugging I noticed that TotpSecurityStampBasedTokenProvider uses a fixed timestep of 3 minutes while google authenticator has a default set to 30 seconds. This difference causes the algorithm to generate different codes. It can not be modified in any way either.
The Google Authenticator documentation specifies it has the option but it is not taken into account.
How can I resolve this without creating my own provider?
If you like I can create a pull request that allows users to override the currently hardcoded timestep.
Hi There,
I am trying to extend the Identity framework. Extending IdenityUser works fine, but when I try to entend the IdenityUserRole class, I run into an System.Argument Exception "GenericArguments[5], 'SecondHandWeb.Areas.Identity.Data.SecondHandWebUserRole', on 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore`9[TUser,TRole,TContext,TKey,TUserClaim,TUserRole,TUserLogin,TUserToken,TRoleClaim]' violates the constraint of type 'TUserRole'." in IdentityHostingStartup.cs
services.AddIdentity<SecondHandWebUser, SecondHandWebRole>( )
.AddEntityFrameworkStores<SecondHandWebContext>()
.AddDefaultTokenProviders()
.AddDefaultUI();
the constructor for my Context looks like this:
public class SecondHandWebContext : IdentityDbContext<SecondHandWebUser, IdentityRole<string>, string, IdentityUserClaim<string>, SecondHandWebUserRole, IdentityUserLogin<string>, IdentityRoleClaim<string>, IdentityUserToken<string>>
I am using the latest Nugetpackage, Microsoft.AspNetCore.Identity.EntityFrameworkCore 5.0
who can I solve this??
Kind regards,
Martin
Hi everyone,
I am new to asp.net core and i started working on asp.net from version 5.0 core. I have switched to asp.net from laravel php framework. This was my brief introduction. I have been working on asp.net and using database first approach i built dbcontext and implemented my whole system in asp.net but in start i wanted to use identity scaffolding and use all commands that added a new identitydbcontext. So i have now two dbcontext one is asp.net core default with only identity and other is my database from db first approach.
I have implemented the default identity system by using
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = false)
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();
But after this i wanted to authenticate users against a custom model tblemployee with fields i.e phone and scale. But when i try to add this by using a method that I found here Asp.net core 2.0 multiple identity .
My code to do that is
services.AddIdentityCore<TblEmployee>().AddEntityFrameworkStores<DbBzuCCContext>().AddDefaultTokenProviders();
But the code is not working it says that extend from IdentityUser but i can't use identityuser fields in my model. I just want to use my 2 fields to work as additional identity provider. Is there any way in middle ware to change default route for different identity and all my previous controllers to be used from default identity but new one with other identity.
Any help will be highly appreciated.
Regards,
I consider this a bug in functionality as there should never get into an infinite loop. I've tried this question with IDS 4 team but they don't respond well. I've got a base asp.net core 3.1 application, trying to integrate it with Identity Server 4. Login page works, user gets authenticated. I've added code for the event handlers in
.AddOpenIdConnect("oidc", options =>
OnTicketReceived the Principal Identity is populated with claims, sub, name and a few others. User shows as authenticated. However, OnRedirectToIdentityProvider keeps firing in a loop. If you watch the browser, you see the code_challenge value constantly changing. Not sure that's an indicate or anything other than I'm stuck in an infinite loop. My first question, how can we enable some type of authentication logging to try and determine what is causing a problem with the asp.Net core Identity code? This has been a nuisance for a long time. At the very least we should be able to implement logging or debugging to try and determine why it's getting stuck in a loop and continually redirects. I just switched to trying IE 11 & Edge and sign in, get redirected back to the Signin-oidc link and I see a correlation failed message on the page. (I'm looking into that now.)
Is there a way to do this? Like an error code that will return when the email confirmation token has expired?
For example if the error code was "TokenExpired" I could use the following to return the user to a specific view which gives them advice on a process to follow if their token has expired:
var result = await _userManager.ConfirmEmailAsync(user, code);
if (result.Succeeded) return View("ConfirmEmail");
return View(result.Errors.Any(c => c.Code == "TokenExpired") ? "TokenExpired" : "Error");
Nuget has new Microsoft.AspNet.Identity.* versions available (2.2.2), but it is impossible to get any information about what has changed compared to previous versions or which state of source code maps to given version for manual verification.
Please do add all releases to publicly visible release notes (or github Releases page), add link to it to nuget package metadata, and tag corresponding codebase in git.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.