AddToRole() method doesn't result in db entry in ASP.NET Identity - c#

I'm using ASP.NET Identity in my ASP.NET MVC app. My problem occures while adding user to role. There isn't any exception, but as a result of um.AddToRole() no db entry is added to AspNetUserRoles table. My action method looks like that:
public ActionResult GrantAdmin(string id)
{
ApplicationUser user = um.FindById(id);
if (!rm.RoleExists("admin"))
{
rm.Create(new IdentityRole("admin"));
}
um.AddToRole(user.Id, "admin");
return View((object)user.UserName);
}
um is an object of UserManager class:
private UserManager<ApplicationUser> um = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
What can be a reason of that kind of application behavior? Any idea?
===EDIT===
It is my DbContext:
public ApplicationDbContext()
: base("DefaultConnection")
{
}
And Default Connection in Web.config:
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-RecommendationPlatform-20140404055015.mdf;Initial Catalog=aspnet-RecommendationPlatform-20140404055015;Integrated Security=True" providerName="System.Data.SqlClient" />

When working with ASP.NET Identity it is important to remember that many operations return a result object where eventual errors are stored. There are no exceptions. Therefore one should check the result object for success after every operation. This is true not only for roles but for most methods that save data to the database. Even if it works you should still test for success and eventually throw an exception if the result is not success.
As per the comments in your case the problem was invalid username.

Related

How to get users from a existing database for identityServer4

i try to understand how i can bind users (email, password, firstname, lastname and os on) which are stored in an existing database (located: localhost:3306) into my identityserver4 project so that i can use these information to login a user or register a new user into that database?
I read some tutorials (specially http://docs.identityserver.io/en/release/quickstarts/8_entity_framework.html) but i think this is always for db in the same project. my db isn´t in the same project.
In this context i read about asp.net-core Identity. but i don´t understand completely how that´s related.
Can someone tell me how can i bind a db in my project and what´s the role of identity with application User and so on?
thanks in advance
This article is more relevant to your situation. The one you linked is for configuration data and not for user data:
http://docs.identityserver.io/en/release/quickstarts/6_aspnet_identity.html
In short, you want to access your user data through Asp.Net Core Identity.
You need to:
Make a user class containing the relevant fields as your database
Create an EntityFramework DbContext class to map your database to your class
Register your user class and dbcontext with aspnet core identity
Tell IdentityServer to use AspNetIdentity
This is what your Startup ConfigureServices method might look like once implemented. Not pictured here is the DbContext and User classes you need to make.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<YourUserStoreDbContextHere>(options =>
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
services.AddIdentity<YourUserClassHere, YourRoleClassHereIfAny>()
.AddEntityFrameworkStores<YourUserStoreDbContextHere>()
.AddDefaultTokenProviders();
services.AddIdentityServer()
// Other config here
.AddAspNetIdentity<YourUserClassHere>();
}
Refer to the docs on AspNet Identity for details on configuring your user class and dbcontext: https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity
You need to implement your own UserStore (example)
public async Task<TapkeyUser> ValidateCredentialsAsync(string username, string password)
{
//This is pseudo-code implement your DB logic here
if (database.query("select id from users where username = username and password = password")
{
return new User(); //return User from Database here
} else {
return null;
}
}
And use this in your AccountController:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginInputModel model)
{
if (ModelState.IsValid)
{
// use our custom UserStore here
--------> if (_users.ValidateCredentials(model.Username, model.Password))
{
AuthenticationProperties props = null;
// only set explicit expiration here if persistent.
// otherwise we reply upon expiration configured in cookie middleware.
if (AccountOptions.AllowRememberLogin && model.RememberLogin)
{
props = new AuthenticationProperties
{
IsPersistent = true,
ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration)
};
};
// issue authentication cookie with subject ID and username
var user = _users.FindByUsername(model.Username);
await _events.RaiseAsync(new UserLoginSuccessEvent(user.Username, user.SubjectId, user.Username));
await HttpContext.Authentication.SignInAsync(user.SubjectId, user.Username, props);
// make sure the returnUrl is still valid, and if yes - redirect back to authorize endpoint or a local page
if (_interaction.IsValidReturnUrl(model.ReturnUrl) || Url.IsLocalUrl(model.ReturnUrl))
{
return Redirect(model.ReturnUrl);
}
return Redirect("~/");
}
await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials"));
ModelState.AddModelError("", AccountOptions.InvalidCredentialsErrorMessage);
}
// something went wrong, show form with error
var vm = await _account.BuildLoginViewModelAsync(model);
return View(vm);
}

Web API 2.0 Using MySQL Identity Provider, AuthContext?

I am attempting to setup token authentication using ASP.NET Identity in a WebAPI 2 with a MySQL Backend using this tutorial.
http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/
Unfortunately, this example uses Entity Framework and I am attempting to substitute it where ever I can (if it is even possible) with MySQL.
I have so far come to step 5, creating an authentication repository. This is the example given:
public class AuthRepository : IDisposable
{
private AuthContext _ctx;
private UserManager<IdentityUser> _userManager;
public AuthRepository()
{
_ctx = new AuthContext();
_userManager = new UserManager<IdentityUser>(new UserStore<IdentityUser>(_ctx));
}
public async Task<IdentityResult> RegisterUser(UserModel userModel)
{
IdentityUser user = new IdentityUser
{
UserName = userModel.UserName
};
var result = await _userManager.CreateAsync(user, userModel.Password);
return result;
}
public async Task<IdentityUser> FindUser(string userName, string password)
{
IdentityUser user = await _userManager.FindAsync(userName, password);
return user;
}
public void Dispose()
{
_ctx.Dispose();
_userManager.Dispose();
}
}
I substituted UserManager for MySQLUserManager, but I cannot make an AuthContext.
Does anybody know what I must reference, or replace.
Maybe I do not even need to reference it, as in my IdentityConfig.cs file I only have:
//Old entity framework stuff
//var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
//shiny new mysql stuff
var manager = new ApplicationUserManager(new MySqlUserStore<ApplicationUser>());
(based off this tutorial http://blog.developers.ba/asp-net-identity-2-1-for-mysql/)
If I need an application user, should I pass it somehow?
I re-read the tutorial and came across this snippet, it appears to be a connection string of some sort.
<connectionStrings>
<add name="AuthContext" connectionString="Data Source=.\sqlexpress;Initial Catalog=AngularJSAuth;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />
</connectionStrings>
What could or should I replace it with?

SQL Server connection error when checking User Roles inside a view

When i put this in my Index.cshtml:
#if (Request.IsAuthenticated && User.IsInRole("Admin"))
{
<li>Gerenciar</li>
}
It throws this error:
An exception of type 'System.Web.HttpException' occurred in System.Web.dll but was not handled in user code
Additional information:
It is not possible to connect with the SQL Server database
Everything is working SQL Server related, it creates the database, create users fine.
I already looked at other questions and there is no answer that helps!
UPDATE 1
I initialize my context using the default Identity 2.0 context:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
static ApplicationDbContext()
{
// Set the database intializer which is run once during application start
// This seeds the database with admin user credentials and admin role
Database.SetInitializer<ApplicationDbContext>(new ApplicationDbInitializer());
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
public System.Data.Entity.DbSet<Gatos.Models.Gato> Gato { get; set; }
public System.Data.Entity.DbSet<Gatos.Models.Formulario> Formulario { get; set; }
public System.Data.Entity.DbSet<Gatos.Models.Imagem> Imagem { get; set; }
}
My connection string:
<add name="DefaultConnection" connectionString="Data Source=Bruno-PC;Initial Catalog=Gatos;User Id = sa; Password = *******" providerName="System.Data.SqlClient" />
Update 2
Now my:
[Authorize(Roles="Admin")]
in my controllers are throwing the same error! This is driving me insane!
Are you using a custom Membership for authentication / Authorization?
As a Shortcut, try removing the following line from your main Web.Config:
<roleManager enabled="true" />
Also, take a look at the following page regarding this issue and the solution:
MVC 5 - RoleManager
Try setting your password in a connection string instead of asterisk (*)
<add name="DefaultConnection" connectionString="Data Source=Bruno-PC;Initial Catalog=Gatos;User Id = sa; Password = your_db_pwd" providerName="System.Data.SqlClient" />

The entity type IdentityUser is not part of the model for the current context

I see the same issue as this question, but the scenario presented there doesn't seem to apply so I think I have a different issue. In fact, I'm seeing several questions on SO that are similar, each with different causes and solutions, so I think this error must be caused from a high level. That said...
I have an EF code-first database model and I'm trying to use IdentityUser to extend a standard registration for my MVC 5 site.
I have my extended UserModel:
namespace MyMvcSite.Models
{
public class UserModel : IdentityUser
{
public string BillingId { get; set; }
public virtual ICollection<DatabaseModel> Databases { get; set; }
}
}
And my context:
using MyMvcSite.Models;
namespace MyMvcSite.Web
{
public class AuthContext : IdentityDbContext<UserModel>
{
public AuthContext() : base("AuthContext") { }
}
}
Now, when I execute the code to register a user:
public async Task<IdentityResult> RegisterUser(UserModel user)
{
user.Email = user.UserName;
var result = await _userManager.CreateAsync(user);
return result;
}
I get this error:
The entity type IdentityUser is not part of the model for the current context.
I can't figure out what this error means, because it looks like I have everything correct. Can anyone tell what might be going wrong???
I know my connectionString AuthContext is correct because I have used it previously.
When you are using a custom user class with ASP.NET Identity, you have to make sure that you explicitly specify the custom user class type <T> to both the UserManager and the UserStore on instantiation.
private UserManager<UserModel> _userManager;
public AccountController()
{
AuthContext _ctx = new AuthContext();
UserStore<UserModel> userStore = new UserStore<UserModel>(_ctx);
_userManager = new UserManager<UserModel>(userStore);
}
or in shorter form (like your reply comment):
private UserManager<UserModel> _userManager;
public AccountController()
{
AuthContext _ctx = new AuthContext();
_userManager = new UserManager<UserModel>(new UserStore<UserModel>(_ctx));
}
If the type is allowed to defaulted to IdentityUser when you want to use a custom class you will experience the error you reported.
I was having this same problem, and I recall having a similar problem working with SimpleMembership in MVC4.
I’m doing database first development, so I have an EDMX file. Turns out, ASP.NET Identity does not like the connection string that is created when you generate your .edmx model file. If you are using a. EDM connection string in :base(“EDMConnString”) you will most likely have this problem.
I fixed this by creating a standard connection string that pointed to the database where the ASP.NET Identity tables are (in my case the same database), used that connection string in :base, and it worked.
Something like this
<add name="IdentityConnection" connectionString="data source=THEJUS\SQLSERVER2014;initial catalog=IdentitySample;integrated security=True;MultipleActiveResultSets=True;App=IdentitySample.Admin" providerName="System.Data.SqlClient" />
I got this error when I introduced DI to my project. Using AutoFac and Identity I had to add the following: builder.RegisterType<ApplicationDbContext>().As<DbContext>().InstancePerLifetimeScope();
Without this, when AutoFac was creating my UserStore instance, it was using the default UserStore() ctor which creates a new IdentityDbContext, not my ApplicationDbContext.
With this line, UserStore(DbContext context) ctor gets called, with my ApplicationDbContext.
Here is some step i figured out while resolving this issue
First Check your database for Table of ASP.Net Identity
Create these table on your database if not exist you can also apply migration
Check the below image and verify your code
Register Action
IdentityDbContext Class

Asp.NET Identity IdentityUser Custom Properties Cause Runtime Error

I am writing an application using the VS2013 SPA template that includes Asp.NET Identity, WebAPI2, KnockoutJS and SqlServer Express 2012.
I started off using the IdentityUser class to handle my users and that worked just fine. I was able to add and login as a user with no problem. I then wanted to add custom information to the IdentityUser (there was an article I can no longer find).
As a result, I created an User class that inherited from IdentityUser as seen below.
public class User : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Then I updated all the references in the project from IdentityUser to User.
Now, whenever I try to login I get the following error:
The entity type User is not part of the model for the current context.
The thing is, I have a DBInitializer (public class ApplicationDBInitializer : DropCreateDatabaseAlways<ApplicationDBContext>) that always recreates the database and adds some test users and the tables are created and the users are added successfully.
On the off chance it matters, here is my cxn string: <add name="DefaultConnection" connectionString="Server=.\SQLEXPRESS;Database=ibcf;Trusted_Connection=True;" providerName="System.Data.SqlClient" />
and my DBContext
public class ApplicationDBContext : IdentityDbContext<User>
{
public ApplicationDBContext()
: base("DefaultConnection")
{
}
}
Why is this error happening?
The issue was that the Startup.Auth.cs continued to reference the default IdentityDbContext<User> DB context. After updating the class to reference my ApplicationDBContext the issue was resolved.
static Startup()
{
...
UserManagerFactory = () => new UserManager<User>(new UserStore<User>(new ApplicationDBContext()));
...
}

Categories