GithubHelp home page GithubHelp logo

grandchamp / identity.dapper Goto Github PK

View Code? Open in Web Editor NEW
266.0 24.0 62.0 865 KB

Identity package that uses Dapper instead EntityFramework for use with .NET Core

License: MIT License

C# 99.73% Shell 0.12% Dockerfile 0.15%
dapper identity dotnet dotnetcore aspnetcore aspnet aspnet-core aspnet-mvc aspnetcoreidentity

identity.dapper's People

Contributors

askingalot avatar bgrainger avatar ervwalter avatar grandchamp avatar peperud avatar steine avatar techbrij avatar terzano avatar tetsuo13 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

identity.dapper's Issues

ExternalLogin issues

I just managed to setup external login with Google. Ran into a few issues:

  1. /src/Identity.Dapper/Extensions/SqlQueryParametersExtensions.cs
public static string SelectFilterWithTableName(this IEnumerable<string> propertyNames, string tableName)
        {
            var propertyNamesArray = propertyNames.ToArray();
 
            var filterBuilderArray = new List<string>(propertyNamesArray.Length);

            for (int i = 0; i < propertyNamesArray.Length; i++)

The line below added " to propertynames, allthough the propertyNamesArray already contained "propertyName". Deleting them here fixed it for me, I dont know if it really should be changed somewhere else instead?

                filterBuilderArray.Add($"\"{tableName}\".{propertyNamesArray[i]}");


            return string.Join(", ", filterBuilderArray);
        }

The file /src/Identity.Dapper.SqlServer/Models/SqlServerConfiguration.cs
GetUserLoginByLoginProviderAndProviderKeyQuery = "SELECT TOP 1 %USERFILTER% FROM %SCHEMA%.%USERTABLE%, %SCHEMA%.%USERLOGINTABLE% WHERE LoginProvider = %LOGINPROVIDER% AND ProviderKey = %PROVIDERKEY%";

So I changed it to
GetUserLoginByLoginProviderAndProviderKeyQuery = "SELECT TOP 1 %USERFILTER% FROM %SCHEMA%.%USERTABLE%, %SCHEMA%.%USERLOGINTABLE% WHERE %SCHEMA%.%USERTABLE%.Id = %SCHEMA%.%USERLOGINTABLE%.UserId AND LoginProvider = %LOGINPROVIDER% AND ProviderKey = %PROVIDERKEY%"; to get it working.

Don't have the skillz to make changes and PR, so hoping someone else will. Sorry :)

User Information not updated on FindByLoginAsync

Steps to replicate:

Login user via external provider and then grab user information.

var info = await _signInManager.GetExternalLoginInfoAsync();
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, false);
var user = await _userManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey);

The user object does not have its Id or any of the fields filled in. The login succeeds and the UserName field gets populated, but nothing else. Is this a bug or intended? If intended why is that so, is it possible to get it to fill out other information such as UserId?

User and Role extensions can't be resolved

For my project I created extension models for each of the Identity.Dapper.Entities classes so that I can customize the various models. However, when I then extended the stores and repos I run into problems because the stores and repos are based on the DapperIdentityUser<int> and DapperIdentityRole<int> classes, not the DapperIdentityUser<TKey, TUserClaim, TUserRole, TUserLogin> and DapperIdentityRole<TKey, TUserRole, TRoleClaim> classes.

Ex:

public class User : DapperIdentityUser<int, UserClaim, UserRole, UserLogin>
{
    
}

public class UserRepository : UserRepository<User, int, UserRole, RoleClaim>, IUserRepository
{
    private readonly IConnectionProvider _connectionProvider;
    private readonly ILogger<UserRepository> _log;
    private readonly SqlConfiguration _sqlConfiguration;
    private readonly IRoleRepository _roleRepository;
    //private readonly IRoleRepository<DapperIdentityRole<int>, int, UserRole, RoleClaim> _roleRepository;

    public UserRepository(IConnectionProvider connProv, 
                          ILogger<UserRepository> log, 
                          SqlConfiguration sqlConf,
                          //IRoleRepository<DapperIdentityRole<int>, int, UserRole, RoleClaim> roleRepo
                          IRoleRepository roleRepo
                        )
            : base(connProv, log, sqlConf, roleRepo)
    {
        _connectionProvider = connProv;
        _log = log;
        _sqlConfiguration = sqlConf;
        _roleRepository = roleRepo;
    }
    // more methods here
}

This cannot compile because

namespace Identity.Dapper.Repositories
{
    public class UserRepository<TUser, TKey, TUserRole, TRoleClaim> : IUserRepository<TUser, TKey, TUserRole, TRoleClaim>
        where TUser : DapperIdentityUser<TKey>
        where TKey : IEquatable<TKey>
        where TUserRole : DapperIdentityUserRole<TKey>
        where TRoleClaim : DapperIdentityRoleClaim<TKey>

//....
}

here we are expecting TUser : DapperIdentityUser<TKey> but TUser : DapperIdentityUser<int, UserClaim, UserRole, UserLogin>, an ancestor.

Can the repos and stores be altered to use the more general User and Role classes?

NotSupportedException: Store does not implement IRoleClaimStore<TRole>

Hi! Is it possible to assign claims to the roles? So when user logs in, all the claims of his roles are automatically attached to a user. (I want to have permission claims.)

I get the 'NotSupportedException: Store does not implement IRoleClaimStore' exception when try to execute next line of code:

this.roleManager.AddClaimAsync(role, new Claim("Permission", permissionName))

Also as I can see there are no tables in the database to store claim-role relations.

Thank you for help!

What is not ready yet ?

Hello,
Thank you very much for your great job, i am not currently used it, but i will soon. I am developing a .net core api 1.1 app and i use Dapper with a mysql connector instead of Entity Framework. I search for 4 days for a similar project. What is not ready yet to use it?

Roles Empty

I am having an issue with roles.
When I retrieve a user that has roles assigned by doing:

var user = await _userManager.FindByEmailAsync(model.Email);

The roles collection is returned empty. The same occur w/ FindByIdAsync & FindByNameAsync
Thanks for your work on this library.

UserManager.Users is not implemented

When i try to get all Users from Usermanger i get an

An exception of type 'System.NotImplementedException' occurred in Identity.Dapper.dll but was not handled in user code: 'The method or operation is not implemented.'
   at Identity.Dapper.Stores.DapperUserStore`7.get_Users()

exception.

var result = UserManager.Users.ToList();

email stored in uppercase at the mysql database

hi,
first evrything works very well. Thanks for your work. But if i register a new user, the email is stored in uppercase in the mysql database. it´s a litte bit irritating, if you want to show the email at your spa (or other homepage) and it´s in upperacse.
So my questioin is:
is it only a problem by me or is it "normal" and wanted by you. At the mysql code for the database, i can´t find something that the email should stored in uppercase.

Thanks for your help.

Environment.OSVersion

When you update your project to the latest libraries, you will find that Environment.OSVersion is now deprecated. This project seems to use it in QueryList class.

var platform = Environment.OSVersion.Platform.ToString();

Logo for package

If someone is interested in making a simple logo for the project, will be welcome.

RTM Update

Make API compatible with .NET Core RTM.

Support standard ConnectionString setting and format

Identity.Dapper should support ConnectionString configuration out of the box. Chances are the project will require a connection to a DB and will use the standard ConnectionString settings. Identity.Dapper should simply re-use that be default instead of having their own ConnectionProvider.

Identity.Dapper connection information requires that the username and password be added as separate JSON fields in the settings files, while normally the credentials are within the ConnectionString itself as we can see:
https://www.connectionstrings.com/postgresql/
and
https://docs.microsoft.com/en-us/azure/postgresql/connect-csharp

string connString = String.Format( "Server={0}; User Id={1}; Database={2}; Port={3}; Password={4};", Host, User, DBname, Port, Password);

This will allow us to have one ConnectionString for our app and Identity

Unit tests

Cover entire project with unit tests.

PostgreSqlConfiguration.cs default schema

Hello guys,

I'm new to the .Net world so I might have missed something,

Can we discuss the choice of "dbo" as a default schema for postgres?
Shouldn't it be "public" instead as it is afaik the most common schema used for pgsql?

image

Maybe it would be nice to have the opportunity to change it in any way, Sorry for the inconvenience if this is already possible but didn't found the way to do it.

Wrap Table Names with [ ]

Hi, I noticed that you don't wrap your table names with [ ]. By that I mean if you query on [dbo].User you will get an error because User is a reserved keyword. However if you query [dbo].[User] then it will work. In any case, I would suggest updating the scripts in the respective projects to wrap those and thus allow people to name their tables however they want without having to change your code too much.

I know you don't have that problem now because you prefixed your table names with Identity, but if I wanted to change those names to my custom names then I will basically rewrite your adapter dlls, but it would be nice not to have to rewrite too much code to make it work and only have to update the variable names where your tables are stored.

Dependency injection not working for SqlServerConnectionProvider

the project as I downloaded it, works fine. But I needed to customize it a bit.
I took the project here, and incorporated it into a new .net Core 2.1 project. In the process, I somehow broke it. The part I broke is related to dependency injection, and I'm not seeing the issue.

In my Startup.CS,
services.ConfigureDapperConnectionProvider<SqlServerConnectionProvider>(Configuration.GetSection("DapperIdentity")) .ConfigureDapperIdentityCryptography(Configuration.GetSection("DapperIdentityCryptography")) .ConfigureDapperIdentityOptions(new DapperIdentityOptions { UseTransactionalBehavior = false });
I'm debugging it, and when I get to the code below, the _connectionProviderOptions is null. On the sample project provided, it works fine. As far as I can tell, both projects are identical, so I can't see what I broke. The one difference is that the provided project SDK is NetStandard.Library (2.0.3), and my project SDK is Microsoft.NetCore.App (2.1). So that does pull in different versions of the dependent libraries. I suspect that is why it's broken. Where I am confused, is that when I put the dependency in, I put it in as SqlServerConnectionProvider. When it's refenced below, it's referenced as ConnectionProviderOptions. Granted, I'm new to dependency injection, but to me, that should be null, because they are different types. But in the app provided, it does somehow convert them.

`namespace Identity.Dapper.SqlServer.Connections
{
public class SqlServerConnectionProvider : IConnectionProvider
{
private readonly IOptions _connectionProviderOptions;
private readonly EncryptionHelper _encryptionHelper;
public SqlServerConnectionProvider(IOptions connProvOpts, EncryptionHelper encHelper)
{
_connectionProviderOptions = connProvOpts;
_encryptionHelper = encHelper;
}

    public DbConnection Create()
    {
        if (_connectionProviderOptions.Value == null)
            throw new ArgumentNullException("There's no DapperIdentity configuration section registered. Please, register the section in appsettings.json or user secrets.");

`

Claim definition

Hi guys nice work.
I have found one inconsistency regarding the claim objects. In the System.Security.Claims there is a constructor you are using:

//
// Summary:
// Initializes a new instance of the System.Security.Claims.Claim class with the
// specified claim type, and value.
//
// Parameters:
// type:
// The claim type.
//
// value:
// The claim value.
//
// Exceptions:
// T:System.ArgumentNullException:
// type or value is null.
public Claim(string type, string value);

As you can see if one of the input values is null then an exception is thrown.
In the MSSQL defintion for the table IdentityUserClaim the value is NULL, and therefore unaware dev will get the exception being thrown as soon as he tries to sign in:

CREATE TABLE [IdentityUserClaim](
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[UserId] [int] NOT NULL,
	[ClaimType] [varchar](256) NOT NULL,
	**[ClaimValue] [varchar](256) NULL,**
CONSTRAINT [PK_IdentityUserClaim] PRIMARY KEY CLUSTERED 

services.AddIdentity in .net core 2.0

Hi,
AddDapperIdentityForSqlServer() is not working in .net core 2.0. I'm getting this error
Reference to type 'IdentityBuilder' claims it is defined in 'Microsoft.AspNetCore.Identity', but it could not be found.I updated my project to .net core 2.0 and now having problem with AddDapperIdentityForSqlServer is not available in Startup.cs. Do you know how can I fix this?

not an issue only a question

At the sample web Implementation you add at the CustomUser the filed address. Is it right that a column address is automatically creates at the database? I need some more column at the MysQl database and i´m not sure if i add the columns per hand in that MySql file: https://github.com/grandchamp/Identity.Dapper/blob/master/IdentityTablesMySql.sql or if your code does it for me.

p.s:
but I get an error if i try to implement the IdentityTablesMySql.sql at my MySql server (which is outside of my Identity project). I get the error message: ERROR 1215 (HY000) at line 10: Cannot add foreign key constraint

Thanks for answer

DI Activation

On Identity.Dapper.SqlServer\Extensions\ServiceCollectionExtensions.cs there is an commented implementation with generics in AddStores that i can't make work.
I always get DI activation exception.

Decryption exception

I am experiencing an exception on TryDecryptAES256.
Please see the following PR for more info: #66

System.InvalidCastException: Invalid cast from 'System.String' to 'System.Guid'.

I believe there is an issue when the primary key is a GUID.

The issue is probably on line 260 in the DapperUserStore
var result = await _userRepository.GetByIdAsync((TKey)Convert.ChangeType(userId, typeof(TKey)));

this could maybe be an alternative:

T t = (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromInvariantString(text);

https://stackoverflow.com/questions/393731/generic-conversion-function-doesnt-seem-to-work-with-guids#393787

Integration tests

Since much of the problems are related to raw queries, i think the best way to test is creating a integration tests project.
I'll start working on .NET Core 2.0 branch.

User and Role with guid id get exception

Hello. I want to use guid ids for my app and i created CustomUser and CustomRole as

    public class CustomUser : DapperIdentityUser<Guid>
    {
        
    }

    public class CustomRole : DapperIdentityRole<Guid>
    {
        
    }

set Identity in Startup.cs

services.AddIdentity<CustomUser, CustomRole>(x =>
                                                         {
                                                             x.Password.RequireDigit = false;
                                                             x.Password.RequiredLength = 1;
                                                             x.Password.RequireLowercase = false;
                                                             x.Password.RequireNonAlphanumeric = false;
                                                             x.Password.RequireUppercase = false;
                                                         })
                    .AddDapperIdentityFor<PostgreSqlConfiguration, Guid>()
                    .AddDefaultTokenProviders();

but i get exception while dependecies resolve in my AccountController.cs

        private readonly UserManager<CustomUser> _userManager;
        private readonly SignInManager<CustomUser> _signInManager;
        public AccountController(UserManager<CustomUser> userManager, SignInManager<CustomUser> signInManager)
        {
            _userManager = userManager;
            _signInManager = signInManager;
        }

image

Raw exception

System.InvalidOperationException: Unable to resolve service for type 'Identity.Dapper.Factories.Contracts.IQueryFactory' while attempting to activate 'Identity.Dapper.Repositories.RoleRepository4[Trytoremember.Core.Entities.CustomRole,System.Guid,Identity.Dapper.Entities.DapperIdentityUserRole1[System.Guid],Identity.Dapper.Entities.DapperIdentityRoleClaim1[System.Guid]]'.
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, ISet1 callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Type serviceType, Type implementationType, ISet1 callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, ISet1 callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Type serviceType, ISet1 callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, ISet1 callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, ISet1 callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Type serviceType, Type implementationType, ISet1 callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, ISet1 callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Type serviceType, ISet1 callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, ISet1 callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, ISet1 callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Type serviceType, Type implementationType, ISet1 callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, ISet1 callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Type serviceType, ISet1 callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, ISet1 callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type serviceType, Type implementationType, ISet1 callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Type serviceType, Type implementationType, ISet1 callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor descriptor, Type serviceType, ISet1 callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Type serviceType, ISet1 callSiteChain) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, ISet1 callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType, ServiceProvider serviceProvider)
at System.Collections.Concurrent.ConcurrentDictionaryExtensions.GetOrAdd[TKey,TValue,TArg](ConcurrentDictionary2 dictionary, TKey key, Func3 valueFactory, TArg arg)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
at Microsoft.Extensions.Internal.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
at lambda_method(Closure , IServiceProvider , Object[] )
at Microsoft.AspNetCore.Mvc.Controllers.ControllerActivatorProvider.<>c__DisplayClass4_0.b__0(ControllerContext controllerContext)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.g__CreateController0(ControllerContext controllerContext)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__22.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Builder.RouterMiddleware.d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.d__7.MoveNext()
`
But if change Id back to int everything works well.
Can you help me with this trouble?
Thank you.

SQL Server - Integrated Security

Thank you for all your work which saved a lot of my time.

It would have been better to have an option to set the SQL database credentials to Integrated windows security. I am not sure if I am asking something wrong since I am pretty new to this Asp.Net Core Api.

Thanks

Using GUID instead of int

Hi,

I tried setting up my project to use GUID instead of int on User and Role tables, however, I encounter the following error:

System.TypeLoadException: GenericArguments[0], 'Identity.Dapper.Entities.DapperIdentityUser1[System.Guid]', on 'Identity.Dapper.Stores.DapperUserStore7[TUser,TKey,TUserRole,TRoleClaim,TUserClaim,TUserLogin,TRole]' violates the constraint of type parameter 'TUser'.
at System.RuntimeTypeHandle.Instantiate(RuntimeTypeHandle handle, IntPtr* pInst, Int32 numGenericArgs, ObjectHandleOnStack type)
at System.RuntimeTypeHandle.Instantiate(Type[] inst)
at System.RuntimeType.MakeGenericType(Type[] instantiation)

I followed your instructions by adding the following to Startup.cs

services.AddIdentity<DapperIdentityUser<Guid>, DapperIdentityRole<Guid>>

Table not found in Mysql

I am getting a "Table Identity.IdentityUser does not exist" error when using mysql . My Database Name is DapperIdentityTest .

Sql Zombie transactions

So I basically have a simple app with all of the classes extended (as discussed in a separate issue). I created 5 users and 3 roles and then made a simple UI where I can drag/drop a user(s) between the different roles. I'm using this as a simple test for the sql and dapper plugin stuff.

[HttpPost]
public async Task<IActionResult> UpdateUserRoles([FromBody] UpdateUserRolesViewModel request)
{
    var success = true;
    var message = "";

    if (!User.IsOwner())
    {
        request.NewOwners = new List<int>();
        message = "Admins cannot create Owners!";
    }
    var allRoles = new List<string>() { "Owner", "Admin", "User" };
    try
    {
        var tasks = new List<Task>();
        tasks.AddRange(request.NewOwners.Select(o => ProcessRoleChange(o, "Owner", allRoles)));
        tasks.AddRange(request.NewAdmins.Select(a => ProcessRoleChange(a, "Admin", allRoles)));
        tasks.AddRange(request.NewUsers.Select(u => ProcessRoleChange(u, "User", allRoles)));

        await Task.WhenAll(tasks);
    }
    catch (Exception ex)
    {
        success = false;
        message = ex.Message;
    }

    return Json(new { Success = success, Message = message });
}
    
private async Task ProcessRoleChange(int userId, string newRole, List<string> allRoles)
{
    var user = await _userDataService.FindByIdAsync(userId.ToString());

    if (user.Id == 0)
        return;

    var currRoles = await _userDataService.GetRolesAsync(user);
    var toRemove = currRoles.Where(cr => allRoles.Contains(cr));

    await Task.WhenAll(toRemove.Select(r => _userDataService.RemoveFromRoleAsync(user, r)));

    await _userDataService.AddToRoleAsync(user, newRole);
}

The basics of this work fine, but if I do it a few times it will eventually start failing. I can debug into the catch and get this stack trace:

at System.Data.SqlClient.SqlTransaction.ZombieCheck()
at System.Data.SqlClient.SqlTransaction.Rollback()
at Identity.Dapper.Stores.DapperUserStore`7.RollbackTransaction() in C:\DevWork\SandboxCore\src\Identity.Dapper\Stores\DapperUserStore.cs:line 82
at Identity.Dapper.Stores.DapperUserStore`7.<UpdateAsync>d__63.MoveNext() in C:\DevWork\SandboxCore\src\Identity.Dapper\Stores\DapperUserStore.cs:line 931
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Identity.UserManager`1.<UpdateUserAsync>d__159.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Identity.UserManager`1.<AddToRoleAsync>d__99.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at SandboxCore.Controllers.AdminController.<ProcessRoleChange>d__4.MoveNext() in C:\DevWork\SandboxCore\src\SandboxCore\Controllers\AdminController.cs:line 93
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at SandboxCore.Controllers.AdminController.<UpdateUserRoles>d__3.MoveNext() in C:\DevWork\SandboxCore\src\SandboxCore\Controllers\AdminController.cs:line 69

My hunch here is that we just simply aren't thread safe when reusing the DbTransaction.

if (transaction == null)
{
     using (conn = _connectionProvider.Create())
     {
          await conn.OpenAsync(cancellationToken);

          return await insertFunction(conn);
      }
 }
 else
 {
       conn = transaction.Connection;
       return await insertFunction(conn);
  }

This is a snippet from the UserRepository.AddToRole method. If the connection gets closed between the if check and the else block, we die in a blaze of glory, right?

AddDapperIdentityForMySql Error CS7069

Getting a

Reference to type 'IdentityBuilder' claims it is defined in 'Microsoft.AspNetCore.Identity', but it could not be found

on this line of code in startup.cs:
services.AddIdentity<DapperIdentityUser, DapperIdentityRole<int>>() .AddDapperIdentityForMySql();

Does not connect to the database when I use a remote database (SQL Server)

ERROR:

2018-09-27 10:42:52.5350||ERROR|Identity.Dapper.Repositories.UserRepository|Login failed for user ''. System.Data.SqlClient.SqlException (0x80131904): Login failed for user ''.
at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, Object providerInfo, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, Boolean applyTransientFaultHandling)
at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionPool.WaitForPendingOpen()

APPSETTINGS:

"ConnectionStrings": {
"EGestorBase": "Server=192.168.0.252;Database=EGestorBase;User Id=xxxxx;Password=xxxxx"
},
"DapperIdentity": {
"ConnectionString": "Server=192.168.0.252;Database=EGestorBase;User Id=xxxxx;Password=xxxxx"
},
"DapperIdentityCryptography": {
"Key": "RTU0NkM4REYyNzhDRDU5MzEwNjlCNTIyRTY5IUQ0RjI=",
"IV": "U29tZVJlYXxseUNvb2xJVg=="
},

Assign Claims

Hi,

I'm trying to figure out how I would add claims to your project. For a simple example, I would like to attach MyCustomField that sits in the Users table. How would accomplish that? I was looking at ServiceCollectionExtension and I see you have some overrides that let you pass in TRoleClaim, but I'm not sure if this is what I'm looking for. And to be honest, I'm not sure how I would pass this along at startup.

NullReferenceException: Object reference not set to an instance of an object.

hi,
i try to run your example. I use mysql and i created the database identity and the tables with the given sql script.
if i try to register a new user i get the follwing error msg:

An unhandled exception occurred while processing the request.
NullReferenceException: Object reference not set to an instance of an object.

Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory+d__5.MoveNext()

NullReferenceException: Object reference not set to an instance of an object.

Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory+<GenerateClaimsAsync>d__5.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory+<CreateAsync>d__9.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNetCore.Identity.SignInManager+<CreateUserPrincipalAsync>d__25.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNetCore.Identity.SignInManager+<SignInAsync>d__30.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Identity.Dapper.Samples.Web.Controllers.AccountController+<Register>d__9.MoveNext() in AccountController.cs

                    // For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713
                    // Send an email with this link
                    //var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
                    //var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
                    //await _emailSender.SendEmailAsync(model.Email, "Confirm your account",
                    //    $"Please confirm your account by clicking this link: <a href='{callbackUrl}'>link</a>");

                    await _signInManager.SignInAsync(user, isPersistent: false);

                    _logger.LogInformation(3, "User created a new account with password.");
                    return RedirectToLocal(returnUrl);
                }
                AddErrors(result);
            }
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeActionMethodAsync>d__12.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeNextActionFilterAsync>d__10.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeInnerFilterAsync>d__14.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeNextResourceFilter>d__22.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeFilterPipelineAsync>d__17.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeAsync>d__15.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Builder.RouterMiddleware+<Invoke>d__4.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware+<Invoke>d__6.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+<Invoke>d__7.MoveNext()
`

I only change your Adress field with FirstName and then i get this error.
Thanks for help

How are you generating AES256 key and init vector?

I try using openssl for encrypt my DB pass with command:
enc -aes256 -nosalt -k password -P

And my output key and iv:
key=5F4DCC3B5AA765D61D8327DEB882CF992B95990A9151374ABD8FF8C5A7A0FE08
iv =B7B4372CDFBCB3D16A2631B59B509E94

After encode to Base64 I get strings twice as long, than in your sample.

What am I doing wrong?

how to create tables in sqlserver?

I'm confused about the tables in DBMS.
for example,if I want to implete the dapperidentity on the sqlserver ,how can I initalize the sqlserver? is there some sql-scripts to execute? and if has ,how to get the script?

Providing Configuration section in .NET Core 2.0 during setup doesn't appear to work.

First of all: THANK you for this! It's mostly been a breeze and I'm excited to see it work once I get this issue sorted out. Really hope this isn't an idiotic question.

In Startup.cs we configure the connection, crypto, and Identity options like so:

var section = Configuration.GetSection("DapperIdentity") as ConnectionProviderOptions; //Value is null!

            services.ConfigureDapperConnectionProvider<PostgreSqlConnectionProvider>(Configuration.GetSection("DapperIdentity"))
                .ConfigureDapperIdentityCryptography(Configuration.GetSection("DapperIdentityCryptography"))
                .ConfigureDapperIdentityOptions(new DapperIdentityOptions { UseTransactionalBehavior = false });

Meanwhile in appsettings.json:

{
  "Logging": {
    "IncludeScopes": false,
    "Debug": {
      "LogLevel": {
        "Default": "Debug",
        "System": "Information",
        "Microsoft": "Information"
      }
    },
    "Console": {
      "LogLevel": {
        "Default": "Debug",
        "System": "Information",
        "Microsoft": "Information"
      }
    }
  },
  "DapperIdentity": {
    "ConnectionString": "User ID=postgres;Password=pass@;Host=localhost;Port=5432;Database=database;Pooling=true;",
    "Username": "postgres",
    "Password": "pass"
  },
  "DapperIdentityCryptography": {
    "Key": "key==",
    "IV": "iv="
  }
}

When I inspect the variable "section" the value of it is null, despite the keys and values clearly being in the JSON. I've obviously looked at the source code where this config section is used with a model - but I'm not sure how it's supposed to with this issue. The end result of this is that when using the library I get the error:

"Parameter name: There's no DapperIdentity:ConnectionString configured. Please, register the value."

I've tried registering the config using your existing types myself in the main Configuration method:

services.Configure<ConnectionProviderOptions>(Configuration.GetSection("DapperIdentity"));
            services.AddScoped<PostgreSqlConnectionProvider>();

But the DI system gets upset:

"Unable to resolve service for type 'Identity.Dapper.Connections.IConnectionProvider' while attempting to activate 'Identity.Dapper.Stores.DapperUserStore'"

It looks like this may be a mismatch of what you have for your examples and your source code - I've noticed that the latest NuGet packages have completely different method signatures from what's in the source code. Not sure if the latest package changes have to be checked in here.

Any guidance would be extremely helpful. Thanks again for your hard work here!

How to use string Id for dapper identity user?

I am having hard time using string type for user id in custom user store. The code breaks at Activator.CreateInstance for idProperty under GetColumns method. Line number 32 om ColumnsBuilderExtensions.cs. On doing some research it is basically caused because System.String does not have a default constructor. Do have any suggestion around how to use string type id's using your your library?

using guid response a cast error

hi,
i get the error:

Invalid cast from 'System.UInt64' to 'System.Guid'. System.InvalidCastException: Invalid cast from 'System.UInt64' to 'System.Guid'. at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider) at Dapper.SqlMapper.Parse[T](Object value) in C:\projects\dapper\Dapper\SqlMapper.cs:line 2969 at Dapper.SqlMapper.<ExecuteScalarImplAsync>d__641.MoveNext() in C:\projects\dapper\Dapper\SqlMapper.Async.cs:line 1193`

this is my ConfigureServices:

public void ConfigureServices(IServiceCollection services)
        {
            

            services.ConfigureDapperConnectionProvider<MySqlConnectionProvider>(Configuration.GetSection("DapperIdentity"))
                    .ConfigureDapperIdentityCryptography(Configuration.GetSection("DapperIdentityCryptography"))
                    .ConfigureDapperIdentityOptions(new DapperIdentityOptions { UseTransactionalBehavior = false }); //Change to True to use Transactions in all operations
            

            services.AddIdentity<CustomUser, CustomRole>(x =>
                                                         {
                                                             x.Password.RequireDigit = false;
                                                             x.Password.RequiredLength = 1;
                                                             x.Password.RequireLowercase = false;
                                                             x.Password.RequireNonAlphanumeric = false;
                                                             x.Password.RequireUppercase = false;
                                                         })


                .AddDapperIdentityFor<MySqlConfiguration, Guid>()
                    .AddDefaultTokenProviders();

            services.AddMvc();

CustomUser and CustomRole:

public class CustomUser : DapperIdentityUser<Guid>
    {
        public string FirstName { get; set; }

        public CustomUser() { }
        public CustomUser(string userName) : base(userName) { }
    }

    public class CustomRole : DapperIdentityRole<Guid>
    {

        public CustomRole() { }
        public CustomRole(string roleName) : base(roleName)
        {
        }
    }

I changed the table for identityUser (MySql) like so:

CREATE TABLE IF NOT EXISTS `identityuser` (
  `Id` CHAR(36) NOT NULL,
  `Username` varchar(256) NOT NULL,
  `Email` varchar(256) DEFAULT NULL,
  `FirstName` varchar(256) DEFAULT NULL,
  `EmailConfirmed` bit(1) NOT NULL,
  `PasswordHash` longtext,
  `SecurityStamp` varchar(38) DEFAULT NULL,
  `PhoneNumber` varchar(50) DEFAULT NULL,
  `PhoneNumberConfirmed` bit(1) NOT NULL,
  `TwoFactorEnabled` bit(1) NOT NULL,
  `LockoutEnd` datetime DEFAULT NULL,
  `LockoutEnabled` bit(1) NOT NULL,
  `AccessFailedCount` int(11) NOT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

Is that a mistake from my side or is that a general bug?

EDIT
if i register someone the data is insert in the database, but i get the error message from above

PasswordSignInAsync throws exception

when i try to login user with PasswordSignInAsync it throws exception

fail: Identity.Dapper.Repositories.RoleRepository[0]
CommandText must be specified
System.InvalidOperationException: CommandText must be specified
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Dapper.SqlMapper.d__311.MoveNext() in C:\projects\dapper\Dapper\SqlMapper.Async.cs:line 389 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Identity.Dapper.Repositories.RoleRepository4.<>c__DisplayClass8_0.<b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Identity.Dapper.Repositories.RoleRepository4.<GetClaimsByRole>d__8.MoveNext() fail: Identity.Dapper.Stores.DapperRoleStore[0] CommandText must be specified fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[0] An unhandled exception has occurred while executing the request System.ArgumentNullException: Value cannot be null. Parameter name: claims at System.Security.Claims.ClaimsIdentity.AddClaims(IEnumerable1 claims)
at Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory2.<GenerateClaimsAsync>d__5.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory1.<CreateAsync>d__9.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at Microsoft.AspNetCore.Identity.SignInManager1.<CreateUserPrincipalAsync>d__25.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at Microsoft.AspNetCore.Identity.SignInManager1.<SignInAsync>d__30.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Identity.SignInManager1.d__52.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at Microsoft.AspNetCore.Identity.SignInManager1.d__33.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at Microsoft.AspNetCore.Identity.SignInManager1.d__34.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at HubPay.Api.Controllers.AccountController.d__7.MoveNext() in C:\Code\HubPayWeb\src\HubPay.Api\Controllers\AccountController.cs:line 63
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__12.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__10.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__22.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Builder.RouterMiddleware.d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.d__7.MoveNext()

This is how i register a user

var result = await _userManager.CreateAsync(user, obj.Password);
            if (result.Succeeded)
            {
                var roleString = RoleEnum.Customer.ToString().ToLower(CultureInfo.InvariantCulture);
                var role = await _roleManager.FindByNameAsync(roleString);

                if (role == null)
                {
                    role = new Role { Name = roleString };
                    await _roleManager.CreateAsync(role);
                    if (!await _userManager.IsInRoleAsync(user, role.Name))
                        await _userManager.AddToRoleAsync(user, role.Name);
                }
                user.Roles.Add(new DapperIdentityUserRole<int> { RoleId = role.Id, UserId = user.Id });
                var userDto = _mapper.Map<UserDto>(user);
                return ApiResult(userDto, OperationStatus.Success);
            }

am i missing something?

Use MySqlConnector for async I/O

The UserRepository code uses Dapper's QueryAsync, which will call DbConnection.ExecuteReaderAsync. It's a long-standing bug in MySql.Data (bug 70111) that async I/O methods are not implemented; thus all these methods will fall back to running synchronously. (See also here and here on Stack Overflow.)

To fix this, you could switch to https://github.com/mysql-net/MySqlConnector, an OSS replacement for MySql.Data that supports true asynchronous I/O; it also has full .NET Standard/.NET Core support.

If you're interested in this, I'd be happy to open a PR.

Missing JOIN criterion on GetRolesByUserIdQuery string.

(SqlServer)
Old:

  • Returned all roles on all users that had a role.
    "SELECT Name FROM %SCHEMA%.%ROLETABLE%, %SCHEMA%.%USERROLETABLE% WHERE UserId = %ID%";

New:
"SELECT Name FROM %SCHEMA%.%ROLETABLE%, %SCHEMA%.%USERROLETABLE% WHERE %SCHEMA%.%ROLETABLE%.Id = %SCHEMA%.%USERROLETABLE%.RoleId AND %SCHEMA%.%USERROLETABLE%.UserId = %ID%";

Only started testing so might find more.

Not Implemented error

I am trying to implement Identity.Dapper
I am getting a Not Implemented error while calling userManager.Users.FirstOrDefault() . I miss something ?

UserManager + UserStore Interaction Issue

I've been working on an implementation of the user and roles stores myself using Dapper and looking at your implementation I noticed something that you might want to think about.

For example in your DapperUserStore class you have the AddToRole method. Within that you call this method:

var result = await _userRepository.AddToRole(user.Id, roleName, cancellationToken, _transaction);

That method will get the ID associated to the roleName provided and insert a new record associating the role to the user ID. Works fine. The issue is the way that the ASP.NET Core Identity UserManager class handles this. Take a look at this method found in the UserManager class:

public virtual async Task<IdentityResult> AddToRoleAsync(TUser user, string role)
{
    ThrowIfDisposed();
    var userRoleStore = GetUserRoleStore();
    if (user == null)
    {
        throw new ArgumentNullException(nameof(user));
    }

    var normalizedRole = NormalizeKey(role);
    if (await userRoleStore.IsInRoleAsync(user, normalizedRole, CancellationToken))
    {
        return await UserAlreadyInRoleError(user, role);
    }
    //  Your implementation of this method is called.
    await userRoleStore.AddToRoleAsync(user, normalizedRole, CancellationToken);
    // Then the update user method is called.
    return await UpdateUserAsync(user);
}

Essentially what will happen is your user repository method will be called to add the role and then the UserManager class will call UpdateUserAsync needlessly, because you handled associating the role already. This situation will happen in quite a few places when using the UserManager. The design the Identity Core folks are going for is to make all changes to the User entity and let the UpdateUserAsync method (which calls your UserStore UpdateAsync method) to do all the work.

I haven't totally gone over all the code in your repository, so maybe you've taken this into account already, but a lot of calls to the UserManager class will result extraneous Updates that aren't required. Not a major issue, but can hurt performance.

Why are you don't include "Id" column to FindByLoginAsync?

Why are you don't include "Id" in some queries of your UserRepository like in FindByLoginAsync?

When I try to sign in via external login, I use FindByLoginAsync, but I doesn't have Id in result and I can't init SignIn without user id.

Sample Website Doesn't work

Hello,

I'm trying to use this project, however, when I download the whole thing and I try to use the sample project, it doesn't work out of the box. I wanted to make a suggestion for the sample project to be configured so that it will work on any machine when downloaded.

I didn't have time to dive in depth and figure out what exactly is wrong, but one of the errors I get is:

Identity.Dapper.Samples.Web\Views\Account\Login.cshtml

'SignInManager' does not contain a definition for 'GetExternalAuthenticationSchemes' and no extension method 'GetExternalAuthenticationSchemes' accepting a first argument of type 'SignInManager' could be found (are you missing a using directive or an assembly reference?)
Operator '==' cannot be applied to operands of type 'method group' and 'int'
foreach statement cannot operate on variables of type '?' because '?' does not contain a public definition for 'GetEnumerator'

Do you have a working sample uploaded somewhere I can use to test and see how all this works?

Can you add a License file?

This looks like a great package. I'd like to know what the license is to know if I can utilize it in my current project. Thanks!

P.S. I'm a big fan of MIT :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.