I want write test and save user in sql ce.This my test:
using (ApplicationContext context = new ApplicationContext())
{
var email = "Shahrooz#s.s";
var username = "shahrooz";
var customUserStore = SmObjectFactory.Container.GetInstance<IUserStore<ApplicationUser, int>>();
var customRoleStore = SmObjectFactory.Container.GetInstance<IApplicationRoleManager>();
var smsService = SmObjectFactory.Container.GetInstance<IIdentityMessageService>();
var emailService = SmObjectFactory.Container.GetInstance<IIdentityMessageService>();
ApplicationUserManager manager = new ApplicationUserManager(customUserStore, customRoleStore, new DpapiDataProtectionProvider(), smsService, emailService);
context.Database.Connection.Open();
manager.CreateAsync(new ApplicationUser { Email = email, UserName = username }, Guid.NewGuid().ToString()).Wait();
var applicationUser = context.Users.Find(1);
Assert.IsNotNull(applicationUser);
Assert.IsTrue(applicationUser.Email == email);
Assert.IsTrue(applicationUser.UserName == username);
context.Database.Connection.Close();
}
But CreateAsync dont store any thing in database.
What is my problem?
This line:
manager.CreateAsync(.....
this method returns an object IdentityResult that contains boolean for Successful and a list of Errors that you should inspect. Inspect this object for errors and if user was created.
Related
I have an ASP.NET Core 3.1 application using EF Core 3.1.
How can I seed an user with a few claims? I was unable to find any documentation for this.
Here's a method for seeding a super user you can tweak it to suit you
private void SeedUsers(UserManager<AppUser> userManager)
{
//Check if it's already seeded
if (userManager.FindByEmailAsync(_superUserDetails.Email).Result != null)
return;
//Create User
var user = new AppUser
{
UserName = _superUserDetails.UserName,
Email = _superUserDetails.Email,
FirstName = "Clarke",
LastName = "Kent"
};
//Set password
var userResult = userManager.CreateAsync(user, _superUserDetails.Password).Result;
if (!userResult.Succeeded)
throw new SeedingException(userResult.Errors);
//Add superUser Claim
var superUserClaim = new Claim("MyRoleClaimType", "SuperUser", ClaimValueTypes.String, "MyIssuer");
var roleResult = userManager.AddClaimAsync(user, superUserClaim).Result;
if (!roleResult.Succeeded)
throw new SeedingException(roleResult.Errors);
}//SeedUsers
In our project we have a user management system build on the ASP.NET Identity framework.
When a user registers by providing an email, username and password, everything works fine. We are able to get the users ID in the method in every controller that inherit "ApiController".
However, now we are trying to implement external log in providers, and we are starting off with Facebook. The registration is going smooth, and the user is created in our database, just any other user, but without a PasswordHash of cause, and an access token is retured back to the client for further authorization.
All of that is working as it should, but when it comes to the part, where the programmer should be able to receive the users id with "User.Identity.GetUserId", we are having a little problem. The "User.Identity" is containing the right "userName" but the "GetUserId" is always returning "null".
The following is our registration method, and the generation of the access token
[OverrideAuthentication]
[AllowAnonymous]
[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
[Route("RegisterExternal")]
public async Task<IHttpActionResult> RegisterExternal(RegisterExternalBindingModel model)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var verifiedAccessToken = await VerifyExternalAccessToken(model.Provider, model.AccessToken);
if (verifiedAccessToken == null)
{
return BadRequest("Invalid Provider or External Access Token");
}
var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };
IdentityResult result = await UserManager.CreateAsync(user);
if (!result.Succeeded)
{
return GetErrorResult(result);
}
var info = new ExternalLoginInfo()
{
DefaultUserName = model.UserName,
Login = new UserLoginInfo(model.Provider, verifiedAccessToken.user_id)
};
var accessTokenResponse = GenerateLocalAccessTokenResponse(model.UserName, user.Id, model.Provider);
return Ok(accessTokenResponse);
}
catch (Exception e)
{
return null;
}
}
private JObject GenerateLocalAccessTokenResponse(string userName, string userid, string provider)
{
var tokenExpiration = TimeSpan.FromDays(1);
ClaimsIdentity identity = new ClaimsIdentity(OAuthDefaults.AuthenticationType);
identity.AddClaim(new Claim(ClaimTypes.Sid, userid));
identity.AddClaim(new Claim(ClaimTypes.Name, userName));
identity.AddClaim(new Claim("role", "user"));
var props = new AuthenticationProperties()
{
IssuedUtc = DateTime.UtcNow,
ExpiresUtc = DateTime.UtcNow.Add(tokenExpiration),
};
var ticket = new AuthenticationTicket(identity, props);
var accessToken = Startup.OAuthBearerOptions.AccessTokenFormat.Protect(ticket);
JObject tokenResponse = new JObject(
new JProperty("userName", userName),
new JProperty("access_token", accessToken),
new JProperty("token_type", "bearer"),
new JProperty("external_provider", provider),
new JProperty("expires_in", tokenExpiration.TotalSeconds),
new JProperty(".issued", ticket.Properties.IssuedUtc.ToString()),
new JProperty(".expires", ticket.Properties.ExpiresUtc.ToString())
);
return tokenResponse;
}
So all in all, every part of the registration is working as it should, we are just not able to receive the user id of the current user, when it uses an access token for a user created by an external provider.
Well, in case someone in the future needs the answer, it was because the "GetUserId" looked for the claim called "NameIdentifier", so changeing it, made it work.
I used following method to create two roles and two users when my web app starts (In Application_Start() in Global.asax.cs).
However the Administrator role is being created but not the User role. Similar thing happens for user named Admin#admin.com and user named user#user.net. First one is being created but not the second one.
Here is my code.
void create() {
ApplicationDbContext context = new ApplicationDbContext();
IdentityResult IdRoleResult;
IdentityResult IdUserResult;
var roleStore = new RoleStore<IdentityRole>(context);
var roleMngr = new RoleManager<IdentityRole>(roleStore);
if (!roleMngr.RoleExists("Administrator"))
IdRoleResult = roleMngr.Create(new IdentityRole("Administrator"));
roleStore = new RoleStore<IdentityRole>(context);
roleMngr = new RoleManager<IdentityRole>(roleStore);
if (!roleMngr.RoleExists("User"))
IdRoleResult = roleMngr.Create(new IdentityRole("User"));
var userMngr = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
var appUser = new ApplicationUser() { UserName = "Admin#admin.com" };
IdUserResult = userMngr.Create(appUser, "pa$$word");
if (IdUserResult.Succeeded)
IdRoleResult = userMngr.AddToRole(appUser.Id, "Administrator");
userMngr = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
appUser = new ApplicationUser() { UserName = "user#user.net" };
IdUserResult = userMngr.Create(appUser, "user");
if (IdUserResult.Succeeded)
IdRoleResult = userMngr.AddToRole(appUser.Id, "User");
}
Can anybody tell me, what I've done wrong or any alternative way to perform this.
Thanks in advance.
Updated Code:
void createAdmin() {
ApplicationDbContext context = new ApplicationDbContext();
IdentityResult IdRoleResult;
IdentityResult IdUserResult;
var roleStore = new RoleStore<IdentityRole>(context);
var roleMngr = new RoleManager<IdentityRole>(roleStore);
if (!roleMngr.RoleExists("Administrator")) {
IdRoleResult = roleMngr.Create(new IdentityRole("Administrator"));
if (!IdRoleResult.Succeeded)
throw new Exception("Administrator role wasnt created.");
}
if (!roleMngr.RoleExists("User")) {
IdRoleResult = roleMngr.Create(new IdentityRole("User"));
if (!IdRoleResult.Succeeded)
throw new Exception("User role wasnt created.");
}
var userMngr = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
ApplicationUser appUser;
var q = from user in userMngr.Users
where user.UserName == "Admin#admin.com"
select user;
if (q.Count() == 0) {
appUser = new ApplicationUser() { UserName = "Admin#admin.com" };
IdUserResult = userMngr.Create(appUser, "pa$$word");
if (IdUserResult.Succeeded) {
IdRoleResult = userMngr.AddToRole(appUser.Id, "Administrator");
if (!IdRoleResult.Succeeded)
throw new Exception("Admin user wasn't added to Administrator role.");
} else
throw new Exception("Admin user wasn't created.");
}
q = from user in userMngr.Users
where user.UserName == "user#user.net"
select user;
if (q.Count() == 0) {
appUser = new ApplicationUser() { UserName = "user#user.net" };
IdUserResult = userMngr.Create(appUser, "user");
if (IdUserResult.Succeeded) {
IdRoleResult = userMngr.AddToRole(appUser.Id, "User");
if (!IdRoleResult.Succeeded)
throw new Exception("User user wasn't added to User role.");
} else
throw new Exception("User user wasn't created.");
}
}
Here I found that, the code is throwing exception with message "User user wasn't created."
throw new Exception("User user wasn't created.");
I think you should reading error in object result 'IdUserResult', and insert user with function CreateAsync().
In my application I am trying to add Roles and then add Users to a particular role. After searching online I have made this snippet
public ActionResult Install1()
{
ClearLocalDev();
RegisterBindingModel model = new RegisterBindingModel();
model.Email = "mohsin#crondale.com";
model.Password = "123Asd?";
model.ConfirmPassword = "123Asd?";
CreateUser(model);
return RedirectToAction("Index", "Home");
}
public void CreateUser(RegisterBindingModel model)
{
ApplicationDbContext context = new ApplicationDbContext();
IdentityResult identityRoleResult;
IdentityResult identityUserResult;
var roleStore = new RoleStore<IdentityRole>(context); // The context cannot be used while the model is being created. This exception may be thrown if the context is used inside the OnModelCreating method or if the same context instance is accessed by multiple threads concurrently. Note that instance members of DbContext and related classes are not guaranteed to be thread safe.
var roleMgr = new RoleManager<IdentityRole>(roleStore);
if (!roleMgr.RoleExists("Admin"))
{
identityRoleResult = roleMgr.Create(new IdentityRole { Name = "Admin" });
}
var userMgr = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
var appUser = new ApplicationUser
{
UserName = model.Email,
Email = model.Email
};
identityUserResult = userMgr.Create(appUser, model.Password);
if (!userMgr.IsInRole(userMgr.FindByEmail(model.Email).Id, "Admin"))
{
identityUserResult = userMgr.AddToRole(userMgr.FindByEmail(model.Email).Id, "Admin");
}
}
This doesn't get. I get an exception. See the comments in the code to see what and where do I get the error.
Does it have something to do with Async?
I am using Azure as my data storage.
This should work for 4.5:
ApplicationDbContext context = new ApplicationDbContext();
IdentityResult identityRoleResult;
IdentityResult identityUserResult;
var roleStore = new RoleStore<IdentityRole>(context);
var roleMgr = new RoleManager<IdentityRole>(roleStore);
if (!roleMgr.RoleExists("SuperAdmin"))
{
identityRoleResult = roleMgr.Create(new IdentityRole { Name = "SuperAdmin" });
}
var userMgr = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
var appUser = new ApplicationUser
{
UserName = "SuperAdminUser#wingtiptoys.com",
Email = "SuperAdminUser#wingtiptoys.com"
};
identityUserResult = userMgr.Create(appUser, "Pa$$word1");
if (!userMgr.IsInRole(userMgr.FindByEmail("SuperAdminUser#xyz.com").Id, "SuperAdmin"))
{
identityUserResult = userMgr.AddToRole(userMgr.FindByEmail("SuperAdminUser#wingtiptoys.com").Id, "SuperAdmin");
}
Have you created the appropriate database tables for identity provider by running ef migrations? To me it seems that you are trying to invoke a context while the underlying database tables have not yet been created.
I suspect the following line will also cause problems:
identityUserResult = userMgr.Create(appUser, model.Password);
Two things you need to check:
You must hash your password before attempting to save it
The password must adhere to the configured password policy before attempting to save it.
I have the following code in the Seed method of my Configuration.cs file:
var userStore = new UserStore<ApplicationUser>();
var manager = new UserManager<ApplicationUser>(userStore);
IdentityResult result = manager.Create(new ApplicationUser() { UserName = "test#mail.com", Email = "test#mail.com", Name = "Martin Tracey" }, "password");
if (result.Succeeded) { Console.WriteLine("User created successfully"); }
else {
Console.WriteLine("Something went wrong. result is "+result.ToString());
foreach (var error in result.Errors) Console.WriteLine(error);
}
For whatever reason, the manager.Create call is returning null.
Any idea why this method would ever return null?
I figured it out! It's a very simple solution.
My userStorevariable didn't have a DbContext which would allow it to access and write to the Database. The simple solution is to use the context passed into the Seed method. Works like a charm now! See below:
protected override void Seed(MyFirstWebApplication.Models.ApplicationDbContext context)
{
if( !context.Users.Any( u => u.Email == "test#mail.com" ) )
{
var userStore = new UserStore<ApplicationUser>(context);
var manager = new UserManager<ApplicationUser>(userStore);
var user = new ApplicationUser() { UserName = "test#mail.com", Email = "test#mail.com", Name = "Martin Tracey" };
IdentityResult result = manager.Create(user, "password");}
}
}