Custom implementation of ASP.NET Identity - c#

I'm using various resources to try and implement an Identity system with MS Access for an AngularJS app.
I created classes which implement the Identity interfaces I need, and I'm stuck at the stage of creating the Account controller (which will be the API for registeration, login, etc).
The class UserStore implements IUserStore and has the CreateAsync method:
public Task CreateAsync(TUser user)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
var result = userTable.Insert(user);
return Task.FromResult(result);
}
AccountController implements ApiController and has the Register method:
[AllowAnonymous]
[Route("register")]
public async Task<IHttpActionResult> Register(IdentityUser user)
{
var result = await _userStore.CreateAsync(user);
if (result == 0)
{
return InternalServerError();
}
return Ok();
}
userTable.Insert(user) returns an int indicating the number of rows affected in the DB table. The line var result = await _userStore.CreateAsync(user); throws an error, saying it actually returns void, and so void cannot be assigned to var (or to anything else).
I'm having a hard time understanding how to write the Register method and the CreateAsync method so that they will work together.
BTW, I thought I should give up the whole async thing and just make CreateAsync and Register return the int value as-is, but I can't do that since UserStore implements `IUserStore'.

The issue is that the return type cannot be passed from the CreateAsync as it is simply a Task return. It would need to be Task<int> but you cannot do that since it's implementing the IUserStore interface. Why do you need the result, I'm assuming you do not?
Try this instead:
[AllowAnonymous]
[Route("register")]
public async Task<IHttpActionResult> Register(IdentityUser user)
{
await _userStore.CreateAsync(user);
return Ok();
}
Additionally, consider making userTable.Insert(user) an async call if at all possible.
I would suggest not giving up on async/await. Especially for I/O bound operations on a web site like this, they really make your application usable.
If you're really concerned about whether or not the insert might be problematic, try this instead:
public async Task CreateAsync(TUser user)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
var existingUser = await this.FindByIdAsync(user.Id);
if (existingUser != null)
{
await this.UpdateAsync(user);
}
else
{
userTable.Insert(user);
}
}

Related

Hung returning Follows data from Relationships endpoint

I'm trying to return a list of followed users from the Instagram API. I'm on a sandbox account using the InstaSharp wrapper for .NET.
The action method is being called after user is authenticated.
public ActionResult Following()
{
var oAuthResponse = Session["InstaSharp.AuthInfo"] as OAuthResponse;
if (oAuthResponse == null)
{
return RedirectToAction("Login");
}
var info = new InstaSharp.Endpoints.Relationships(config_, oAuthResponse);
var following = info.Follows("10").Result;
return View(following.Data);
}
Try making the method async all the way through instead of making the blocking call .Result which runs the risk of causing a deadlock
public async Task<ActionResult> Following() {
var oAuthResponse = Session["InstaSharp.AuthInfo"] as OAuthResponse;
if (oAuthResponse == null) {
return RedirectToAction("Login");
}
var info = new InstaSharp.Endpoints.Relationships(config_, oAuthResponse);
var following = await info.Follows("10");
return View(following.Data);
}
depending on how info.Follows was implemented.
Looking at the Github repo, the API internally makes a call to a method defined like this
public static async Task<T> ExecuteAsync<T>(this HttpClient client, HttpRequestMessage request)
Which looks like your smoking gun as calling .Result higher up the call stack on this task would result in your experienced deadlock.
Reference Async/Await - Best Practices in Asynchronous Programming

Implementing the Microsoft AspNet Identity IUserLockoutStore

I am using Microsoft.AspNet.Identity for logging into my c# mvc web application. I have implemented the different User Stores including the Lockout User Store. But I can't get it to work properly. In my Custom User Manager I set the max tries, lockout time etc:
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(30);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
If I use the above code and parameters my user never gets locked. If I set the manager.MaxFailedAccessAttemptsBeforeLockout to 2, the my User gets locked after one try. Does anyone have a tutorial on how to correctly implement the "IUserLockoutStore" interface? I've been searching Google all morning and am not getting closer to my goal. Here is my current implementation of the "IUserLockoutStore" interface.
public Task<DateTimeOffset> GetLockoutEndDateAsync(Gebruiker user)
{
var lockOutDate = user.LockOutDate.HasValue ? user.LockOutDate.Value : new DateTimeOffset(DateTime.Now.AddMinutes(-5));
return Task.FromResult(lockOutDate);
}
public Task SetLockoutEndDateAsync(Gebruiker user, DateTimeOffset lockoutEnd)
{
user.LockOutDate = lockoutEnd;
user.IsLocked = true;
return Context.SaveChangesAsync();
}
public Task<int> IncrementAccessFailedCountAsync(Gebruiker user)
{
user.LoginTry++;
return Context.SaveChangesAsync();
}
public Task ResetAccessFailedCountAsync(Gebruiker user)
{
user.LoginTry = 0;
return Context.SaveChangesAsync();
}
public Task<int> GetAccessFailedCountAsync(Gebruiker user) => Task.FromResult(user.LoginTry);
public Task<bool> GetLockoutEnabledAsync(Gebruiker user) => Task.FromResult(true);
public Task SetLockoutEnabledAsync(Gebruiker user, bool enabled)=> Task.FromResult(enabled);
My implementation is very similar to yours except for these two things:
In GetLockoutEndDateAsync I use utc time:
... new DateTimeOffset(DateTime.UtcNow.AddMinutes(-5))
Also (and perhaps more significantly), your return value from IncrementAccessFailedCountAsync should return the count (but you are returning the result of SaveChanges):
public Task<int> IncrementAccessFailedCountAsync(Gebruiker user)
{
user.LoginTry++;
Context.SaveChangesAsync();
return user.LoginTry;
}
It is just a coincidence that SaveChangesAsync also returns an int which is probably why you didn't notice this.
Another note is that you don't have to call Context.SaveChangesAsync() in the first place. This is handled by your implementation of IUserStore. Your IUserLockoutStore (and others like IUserLoginStore and IUserEmailStore etc) don't save to the DB. The infrastructure calls those interfaces to set things, then at the end call IUserStore.UpdateAsync (or .CreateAsync). So it should simply be:
public Task<int> IncrementAccessFailedCountAsync(Gebruiker user)
{
user.LoginTry++;
return Task.FromResult(user.LoginTry);
}

Async code misleading in aspnet identity

I need to implement a custom Storage provider for aspnetidentity.
I had a good look round and i found quite a few.However they seem all wrong to me.
My understing is that if you have a method that ends with "async" than it should by asynchronous.
See example taken from somebody's code and this is scattered all over the place.
I find below very misleading since it's not Async at all from what I can see:
public Task<TUser> FindByIdAsync(int userId)
{
TUser result = userTable.GetUserById(userId) as TUser; //this is not async
if (result != null)
{
return Task.FromResult<TUser>(result);
}
return Task.FromResult<TUser>(null);
}
should this be coded like this?:
public async Task<TUser> FindByIdAsync(int userId)
{
TUser result = userTable.GetUserByIdAsync(userId) as TUser;
if (result != null)
{
return await Task.FromResult<TUser>(result);
}
return await Task.FromResult<TUser>(null);
}
Questions?
Is it correct to do "Task.FromResult"? What I mean is does "Task.FromResult actually turns into synchronous? what should it be?
What is the correct way to code the above? what about configureAwait(false)
should async be "All the way down including datalayer to avoid deadlocking"
any sample code /snippet would be appreciated
many thanks for any feedback
The code is not misleading. ASP.NET Identity framework has been designed to provide an asynchronous interface by returning a Task and indicating this by adding the Async suffix to the method name:
Task<TUser> FindByIdAsync(int userId)
However, the underlying provider may not have asynchronous methods. In that case you cannot create an asynchronous implementation but you still have to implement the interface and to do that will have use Task.FromResult exactly as it is done in your first code snippet.
Implementing an asynchronous method using synchronous code
public Task<TUser> FindByIdAsync(int userId)
{
TUser result = userTable.GetUserById(userId) as TUser;
return Task.FromResult<TUser>(result);
}
If your underlying provider supports asynchronous methods you should use async and await.
Implementing an asynchronous method using asynchronous code
public async Task<TUser> FindByIdAsync(int userId)
{
TUser result = (await userTable.GetUserByIdAsync(userId)) as TUser;
return result;
}
Note that Task.FromResult is not used. Task.FromResult is only needed when you have a TResult created by synchronous code and you have to convert it to Task<TResult> required by asynchronous code.
Sometimes your underlying provider can return the desired Task<TUser> without any further work. In that case you can remove the async and await and still provide an asynchronous implementation. This can result in slightly more efficient code:
public Task<TUser> FindByIdAsync(int userId)
{
Task<TUser> result = userTable.GetUserByIdAsync(userId);
return result;
}
The initial code is definitely not asynchronous. It looks like it was put that way to cope with an API design.
However the proposed change doesn't look async to me either. Task.FromResult just creates a completed task with a result, doesn't make anything asynchronous or executes any kind of awaitable code so you should not await on it.
In your case, assuming GetUserByIdAsync returns a Task<TUser>, and assuming the whole purpose of this code (as it seems) is to always return a completed task (never faulted or cancelled), this could be rewritten as:
public async Task<TUser> FindByIdAsync(int userId)
{
var tResult = userTable.GetUserByIdAsync(userId);
TUser result = null;
try
{
result = await tResult;
}
except
{
// Bad idea, but here goes to your first snippet
}
return Task.FromResult<TUser>(result);
}
Note: this is a bad idea as #PanagiotisKanavos commented, it's hiding a possibly faulted state and you won't ever know if your null result came the user not being found, or if there was an error condition: I'd avoid it.
If a faulted/cancelled state is valid, this could simply be:
public Task<TUser> FindByIdAsync(int userId)
{
return userTable.GetUserByIdAsync(userId);
}
An async method is a way for the compiler to build something that will return a promise our future. In the case of the .NET Framework and C#, that is a Task.
The await instruction takes any awaitable and Task just happens to be one. It doesn't know or care if the method/operations being invoked is really asynchronous or not.
Task.FromResult<T> returns a completed task and if you use it in an await instruction inside an async method it will be considered to have been completed synchronously and execution will continue.
So, using async and await with just calls to Task.FromResult<T> ends up just being a waste of CPU cycles and memory by the compiler generating code that will waste more CPU cycles and memory at run time.
Because an async method always returns a Task a decision was made to make it implicit to improve readability and give it some kind of sync feeling. The compile will wrap the return value in a Task. That's why you can't return Task.FromResult<TUser>(result) or Task.FromResult<TUser>(null) directly and are awaiting it to get the value.
So, the async equivalent of your synchronous code would be:
public async Task<TUser> FindByIdAsync(int userId)
{
var result = await userTable.GetUserByIdAsync(userId) as TUser;
if (result != null)
{
return result;
}
return null;
}
Or:
public async Task<TUser> FindByIdAsync(int userId)
{
return await userTable.GetUserByIdAsync(userId) as TUser;
}

NHibernate session management in RESTful API with Tasks/Threads

I'm building a set of APIs. One of them is a authentication API, that returns JWT tokens. I'm trying to implement a Session per Action approach, with ActionFiltersAttribute. My controller is decorated with this attribute:
public class NHibernateSessionAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
var session = NHibernateSessionManager.SessionFactory.OpenSession();
session.BeginTransaction();
CurrentSessionContext.Bind(session);
}
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
var session = CurrentSessionContext.Unbind(NHibernateSessionManager.SessionFactory)
if (session != null)
{
if (session.Transaction.IsActive)
{
try
{
session.Transaction.Commit();
}
catch
{
session.Transaction.Rollback();
}
}
session.Close();
}
}
}
Where is the problem? To manage the users with NHibernate istead of Entity Framework I've implemented all the needed ASP.NET Identity interfaces, and they all return a Task<T>. For example on the following action:
AccountController.cs
public async Task<IHttpActionResult> ChangePassword(ChangePasswordBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword,
model.NewPassword);
if (!result.Succeeded)
{
return GetErrorResult(result);
}
return Ok();
}
There ChangePasswordAsync calls internally several methods wich have code inside new tasks, where the SessionFactory.GetCurrentSession() causes a NullException. As far as I know, because that's another Thread and context.
In code, the first attempt to save executes with no fail, and the second not. The duplicated code is only to ilustrate the situation.
UserStore.cs
public System.Threading.Tasks.Task UpdateAsync(UserModel user)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
//Here the Session is found
DataProviderI<UserModel, int> prov = new DataProviderImplGeneric<UserModel, int>();
prov.Save(user);
return Task.Factory.StartNew(() =>
{
//Here the Session is NOT found
DataProviderI<UserModel, int> prov2 = new DataProviderImplGeneric<UserModel, int>();
prov.Save(user);
});
}
What's the best way to deal with this and get the same ISession during all the Action ?
As far as I know NHibernate doesn't support async calls and I could refactorize the methods with a return of type Task.FromResult(0) on void cases or Task.FromResult<T>(T) where T is an object, but I would like to know if there's another solution to take advantage of parallelism
Seems like the problem you are dealing with is stemming from the HttpContext being null while inside a task and therefore cannot access the NHibernate session stored inside of the context variable.
You could work around this by getting the ISession before you call into a task.
Add in a constructor to your DataProviderImplGeneric so you manually pass one in.
DataProviderImplGeneric(ISession session) {
this.session = session;
}
just retrieve the session before you call into this from inside a task.
var session = GetCurrentNHibernateSession();
return Task.Factory.StartNew(() => {
var dataProvider = DataProviderImplGeneric<UserModel, int>(session);
return dataProvider.Save(user);
}

IUserStore<TUser>.CreateAsync : how to indicate failure in custom implementation?

I am writing a custom implementation for IUserStore. The signature of the create method is:
public async virtual Task CreateAsync(TUser user)
And that makes sense considering the core interface IUserStore in Microsoft.AspNet.Identity is (which is the same).
However the interface of the UserManager class defined in Microsoft.AspNet.Identity is :
public virtual Task<IdentityResult> CreateAsync(TUser user);
My problem is I don't see how I should pass this IdentityResult to the UserManager since the return type in the store is simply "Task". I have a custom logic to determine if a user can or cannot be created, so I really need to tell the outcome of CreateAsync to the UserManager.
Any idea ?
Looking at the source code for UserManager.CreateAsync (this is for Identity 2.0) you can see that prior to calling IUserStore.CreateAsync, it makes a call to IIdentityValidator<TUser>.ValidateAsync, which is responsible to actually return the relevant IdentityResult object:
public virtual async Task<IdentityResult> CreateAsync(TUser user)
{
ThrowIfDisposed();
await UpdateSecurityStampInternal(user).ConfigureAwait(false);
var result = await UserValidator.ValidateAsync(user).ConfigureAwait(false);
if (!result.Succeeded)
{
return result;
}
if (UserLockoutEnabledByDefault && SupportsUserLockout)
{
await GetUserLockoutStore().SetLockoutEnabledAsync(user, true).ConfigureAwait(false);
}
await Store.CreateAsync(user).ConfigureAwait(false);
return IdentityResult.Success;
}
The main purpose of IUserStore.CreateAsync is to make the call to the underlying data source which saves the data. It seems that you make actually want to implement IIdentityValidator<TUser> and set it on your UserManager instance.
The answer is in the source code, here's a part of the implementation in the UserManager at time of writing :
public virtual async Task<IdentityResult> CreateAsync(TUser user,
CancellationToken cancellationToken = default(CancellationToken))
{
ThrowIfDisposed();
await UpdateSecurityStampInternal(user, cancellationToken);
var result = await ValidateUserInternal(user, cancellationToken);
if (!result.Succeeded)
{
return result;
}
if (Options.Lockout.EnabledByDefault && SupportsUserLockout)
{
await GetUserLockoutStore().SetLockoutEnabledAsync(user, true, cancellationToken);
}
await UpdateNormalizedUserNameAsync(user, cancellationToken);
await Store.CreateAsync(user, cancellationToken);
return IdentityResult.Success;
}
So basically they always return true. This means that in the current version, putting my creation checks in the UserStore goes against the intended usage of the framework.
However I have noticed that this will be changed in the next release. The IUserStore interface will become :
Task<IdentityResult> CreateAsync(TUser user, CancellationToken cancellationToken);
And the UserManager implementation :
public virtual async Task<IdentityResult> CreateAsync(TUser user)
{
ThrowIfDisposed();
await UpdateSecurityStampInternal(user);
var result = await ValidateUserInternal(user);
if (!result.Succeeded)
{
return result;
}
if (Options.Lockout.AllowedForNewUsers && SupportsUserLockout)
{
await GetUserLockoutStore().SetLockoutEnabledAsync(user, true, CancellationToken);
}
await UpdateNormalizedUserNameAsync(user);
await UpdateNormalizedEmailAsync(user);
return await Store.CreateAsync(user, CancellationToken);
}
So putting the creation logic in the UserStore will be possible at that time. This will be a way better design in my opinion as the client shouldn't have to handle the integrity concerns.

Categories