Add claims when creating a new user - c#

I am creating a new User using ASP.NET Core Identity as follows:
new User {
Email = "john#company.com",
Name = "John"
}
await userManager.CreateAsync(user, "password");
I need to add a Claims when creating the user. I tried:
new User {
Email = "john#company.com",
Name = "John",
Claims = new List<Claim> { /* Claims to be added */ }
}
But Claims property is read only.
What is the best way to do this?

You can use UserManager<YourUser>.AddClaimAsync method to add a claims to your user
var user = new User {
Email = "john#company.com",
Name = "John"
}
await userManager.CreateAsync(user, "password");
await userManager.AddClaimAsync(user, new System.Security.Claims.Claim("your-claim", "your-value"));
Or add claims to the user Claims collection
var user = new User {
Email = "john#company.com",
Name = "John"
}
user.Claims.Add(new IdentityUserClaim<string>
{
ClaimType="your-type",
ClaimValue="your-value"
});
await userManager.CreateAsync(user);

Related

why does FindByNameAsync always return null?

trying to authenticate a token through a post request, user always returns null when i check via the username.
public async Task<IActionResult> Login([FromBody] LoginModel model)
{
var user = await _userManager.FindByNameAsync(model.UserName); // user always equals null here
if (user !=null && await _userManager.CheckPasswordAsync(user,model.UserName))
{
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, user.UserName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};
var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("MySuperSecureKey"));
var token = new JwtSecurityToken(
issuer: "http://blah.com",
audience: "http://blah.com",
expires: DateTime.UtcNow.AddHours(1),
claims: claims,
signingCredentials: new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256)
);
return Ok(new
{
token = new JwtSecurityTokenHandler().WriteToken(token),
expiration = token.ValidTo
});
}
return Unauthorized();
}
wondering if the problem is coming from how i seeded my database with this dummy data class?
public class DummyData
{
public static void Initialize(IApplicationBuilder app, IServiceProvider serviceProvider)
{
using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
{
var context = serviceScope.ServiceProvider.GetService<HealthContext>();
var userManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
context.Database.EnsureCreated();
//context.Database.Migrate();
// Look for any ailments
if (context.Ailments != null && context.Ailments.Any())
return; // DB has already been seeded
var ailments = GetAilments().ToArray();
context.Ailments.AddRange(ailments);
context.SaveChanges();
var medications = GetMedications().ToArray();
context.Medications.AddRange(medications);
context.SaveChanges();
var patients = GetPatients(context).ToArray();
context.Patients.AddRange(patients);
context.SaveChanges();
if (!context.Users.Any())
{
ApplicationUser user = new ApplicationUser()
{
Email = "test#test.com",
SecurityStamp = Guid.NewGuid().ToString(),
UserName = "testTest"
};
userManager.CreateAsync(user, "Password123");
context.Users.Add(user);
context.SaveChanges();
}
}
}
After I seed my database i can see my the user created in the fields, its defo there, so not understanding what seems to be the issue here!
The first thing is to check the database to confirm whether your user is successfully created . There are several issues you can check firstly :
For userManager.FindByNameAsync confirm that you are typing the AndyCosStav , not the email .
The CheckPasswordAsync returns a flag indicating whether the given password is valid for the specified user.
public virtual System.Threading.Tasks.Task<bool> CheckPasswordAsync (TUser user, string password);
The second parameter should be the password , i notice you are checking with username :
if (user !=null && await _userManager.CheckPasswordAsync(user,model.UserName))
Password123 may not match the defalut ASP.NET Core identity password
restrict , you must have at least one non alphanumeric character.

Add role to already created application using Azure AD Graph API in C#

How to add roles in application that is already created on azure ad using Azure AD Graph API in c#.
I create role like this in c#:
Guid _id = new Guid();
AppRole appRole = new AppRole
{
AllowedMemberTypes = _AllowedMemberTypes,
Description = "Admins can manage roles and perform all actions.",
DisplayName = "Global Admin",
Id = _id,
IsEnabled = true,
Value = "Admin"
};
What call will be used to add this new role in application using Azure AD Graph API.
Finally i was able to create a new role on azure using Azure Ad Graph API
1) Create a Role:
Guid _id = Guid.NewGuid();
List<String> _AllowedMemberTypes = new List<string> {
"User"
};
AppRole appRole = new AppRole
{
AllowedMemberTypes = _AllowedMemberTypes,
Description = "Admins can manage roles and perform all actions.",
DisplayName = "Global Admin",
Id = _id,
IsEnabled = true,
Value = "Admin"
};
2) Get Application in which role needed to be created:
IPagedCollection<IApplication> pagedCollection = await activeDirectoryClient.Applications.Where(x => x.AppId == AppclientId).ExecuteAsync();
var appObject = pagedCollection.CurrentPage.ToList().FirstOrDefault();
3) Add Role to Applicationa and Update Application:
appObject.AppRoles.Add(appRole as AppRole);
await appObject.UpdateAsync();
You could refer to the code as below to assign application role.
1.get access token
private static async Task<string> GetAppTokenAsync(string graphResourceId, string tenantId, string clientId, string secretKey)
{
string aadInstance = "https://login.microsoftonline.com/" + tenantId + "/oauth2/token";
AuthenticationContext authenticationContext = new AuthenticationContext(aadInstance, false);
var result = await authenticationContext.AcquireTokenAsync(graphResourceId,
new ClientCredential(clientId, userId));
return result.AccessToken;
}
2.Init the graphclient.
var graphResourceId = "https://graph.windows.net";
var tenantId = "tenantId";
var clientId = "client Id";
var secretKey = "secret key";
var servicePointUri = new Uri(graphResourceId);
var serviceRoot = new Uri(servicePointUri, tenantId);
var activeDirectoryClient = new ActiveDirectoryClient(serviceRoot, async () => await GetAppTokenAsync(graphResourceId, tenantId, clientId, secretKey));
3.create role
AppRole appRole = new AppRole
{
Id = Guid.NewGuid(),
IsEnabled = true,
Description = "Admins can manage roles and perform all actions.",
DisplayName = "Global Admin",
Value = "Admin"
};
4.add role assginments
User user = (User) activeDirectoryClient.Users.GetByObjectId("userobjectId").ExecuteAsync().Result;
AppRoleAssignment appRoleAssignment = new AppRoleAssignment
{
Id = appRole.Id,
ResourceId = Guid.Parse(newServicePrincpal.ObjectId),
PrincipalType = "User",
PrincipalId = Guid.Parse(user.ObjectId),
};
user.AppRoleAssignments.Add(appRoleAssignment);
user.UpdateAsync().Wait();

ASP.Net UserManager AddRoleTo not working

with VS 2015 I've created a little MVC App with the default authentification stuff.
I've changed nothing but the code in the registration action of the account controller:
var context = new ApplicationDbContext();
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await UserManager.CreateAsync(user, model.Password);
var roleStore = new RoleStore<IdentityRole>(context);
var roleManager = new RoleManager<IdentityRole>(roleStore);
var userStore = new UserStore<ApplicationUser>(context);
var userManager = new UserManager<ApplicationUser>(userStore);
if (!roleManager.RoleExists("Administrator"))
{
roleManager.Create(new IdentityRole("Administrator"));
}
if (!roleManager.RoleExists("User"))
{
roleManager.Create(new IdentityRole("User"));
}
if (context.Users.Count() == 1)
{
userManager.AddToRole(user.Id, "Administrator");
} else
{
try
{
userManager.AddToRole(user.Id, "User");
}
catch (Exception ex)
{
throw new Exception("Error assigning role: " + ex.Message);
}
}
The first registrated user becomes an "Administrator". Though the "userManager.AddToRole(user.Id, "User");" doesn't throw an exception no following registrated user is assigned to that role (checked the table and also per Authorize(Role...).
I can't figure out what's wrong here.
I've figured it out. I've used generic email addresses with an "+" in the user name, e.g. user+01#mydomain.com. This doesn't cause trouble while registrating and throws no exception when try/catch the AddRoleTo method but in the result stack of the AddRoleTo appears an error that only chars and numbers are allowed for user name.

How to add ApplicationUser as test data in dotnet core

I'm trying to initialize some test data in my database, and having some problems adding password to the ApplicationUser in Identity Framework.
When I have done this earlier, I have used the seed method like this:
protected override void Seed(ApplicationDbContext db)
{
var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(db));
var adminuser = new ApplicationUser { Email = "admin#test.no", UserName = "admin#test.no", FirstName = "admin", LastName = "test" };
userManager.Create(adminuser, "Password1.");
userManager.AddToRole(adminuser.Id, role:"admin");
}
but as the seed method is not supported in dotnet core I have tried to add the dummy data in the following way:
using (var serviceScope =
app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
db.Database.EnsureCreated();
db.AddRange(
new ApplicationUser { UserName = "ola#nordmann.no", Email = "ola#nordmann.no" },
new ApplicationUser { UserName = "test#test.no", Email = "test#test.no" }
);
db.SaveChanges();
I have also tried to use the same method I used in the seed method, but that doesn't work either as I get the following error message on the line were I add result1 to the database:
cannot convert from 'System.Threading.Tasks.Task' to 'Server.Models.ApplicationUser
using (var serviceScope =
app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
var db = serviceScope.ServiceProvider.GetService<ApplicationDbContext>();
var userManager = app.ApplicationServices.GetService<UserManager<ApplicationUser>>();
var au1 = new ApplicationUser { UserName = "test#test.no", Email = "test#test.no" };
var result1 = userManager.CreateAsync(au1, "Test123");
db.Users.Add(result1);
You can use PasswordHasher in combination with user.
i.e.
var user = new User();
var hasher = new PasswordHasher<User>();
db.AddRange(
new ApplicationUser { UserName = "ola#nordmann.no", Email = "ola#nordmann.no", PasswordHash = hasher.HashPassword(user, "Password1") },
);
db.SaveChanges();
If anyone else should be interested, I ended up with the following solution:
public async Task CreateUsersAndRoles(IServiceScope serviceScope)
{
var userManager = serviceScope.ServiceProvider.GetService<UserManager<ApplicationUser>>();
await userManager.CreateAsync(new ApplicationUser { UserName = "ola#nordmann.no", Email = "ola#nordmann.no"}, "Password1.");
}
and call on this method within the Configure method in the startup file like this:
await CreateUsersAndRoles(app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope());

Seed database for Identity 2

I came across a problem for seeding the database with Identity v2. I separated out the IdentityModel from the MVC5 project to my Data Access Layer where I setup EF Migrations as well. So I commented out the code which use inside "IdentityConfig.cs" to create initial user and put the code inside my seed database that looks like this
protected override void Seed(Repository.DataContext.IdentityDb context)
{
// var userManager = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
// var roleManager = HttpContext.Current.GetOwinContext().Get<ApplicationRoleManager>();
var owinContext = new OwinContext();
var userManager = owinContext.GetUserManager<ApplicationUserManager>();
var roleManager = owinContext.Get<ApplicationRoleManager>();
const string name = "admin#admin.com";
const string password = "Admin#123456";
const string roleName = "Admin";
// //Create Role Admin if it does not exist
var role = roleManager.FindByName(roleName);
if (role == null)
{
role = new IdentityRole(roleName);
var roleresult = roleManager.Create(role);
}
var user = userManager.FindByName(name);
if (user == null)
{
user = new ApplicationUser { UserName = name, Email = name };
var result = userManager.Create(user, password);
result = userManager.SetLockoutEnabled(user.Id, false);
}
// // Add user admin to Role Admin if not already added
var rolesForUser = userManager.GetRoles(user.Id);
if (!rolesForUser.Contains(role.Name))
{
var result = userManager.AddToRole(user.Id, role.Name);
}
}
Now when I am running command update-database, I got an error
Value cannot be null.
Parameter name: manager
It looks like, I am getting null in these two lines of code
var userManager = owinContext.GetUserManager<ApplicationUserManager>();
var roleManager = owinContext.Get<ApplicationRoleManager>();
Any suggestion please?
This is the way to avoid using an OWIN context:
protected override void Seed(Repository.DataContext.IdentityDb context)
var roleStore = new RoleStore<IdentityRole>(context);
var roleManager = new RoleManager<IdentityRole>(roleStore);
var userStore = new UserStore<ApplicationUser>(context);
var userManager = new UserManager<ApplicationUser>(userStore);
var user = new ApplicationUser { UserName = "sallen" };
userManager.Create(user, "password");
roleManager.Create(new IdentityRole { Name = "admin" });
userManager.AddToRole(user.Id, "admin");
}
I got this working by using:
protected override void Seed(ApplicationDbContext context)
{
context.Configuration.LazyLoadingEnabled = true;
//var userManager = HttpContext.Current
// .GetOwinContext().GetUserManager<ApplicationUserManager>();
//var roleManager = HttpContext.Current
// .GetOwinContext().Get<ApplicationRoleManager>();
var roleStore = new RoleStore<ApplicationRole, int, ApplicationUserRole>(context);
var roleManager = new RoleManager<ApplicationRole, int>(roleStore);
var userStore = new UserStore<ApplicationUser, ApplicationRole, int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>(context);
var userManager = new UserManager<ApplicationUser, int>(userStore);
...
Hi Under the Startup class please make sure that you have call
app.CreatePerOwinContext(ApplicationDbContext.Create); app.CreatePerOwinContextApplicationUserManager.Create);
app.CreatePerOwinContextApplicationSignInManager.Create);
app.CreatePerOwinContext(ApplicationRoleManager.Create);
Latest stuff is all async & uses Claims.
Here's what worked for me with migrations to add a super user if none exists ...
protected override void Seed(Holos.Service.Models.ApplicationDbContext context)
{
var email = "xxxx#xxxx.com";
var password = "xxxxx";
var userStore = new UserStore<ApplicationUser>(context);
var userManager = new ApplicationUserManager(userStore);
var user = userManager.FindByEmailAsync(email).Result;
if (user == null)
{
var adminUser = new ApplicationUser() { Email = email, UserName = email };
var result = userManager.CreateAsync(adminUser, password);
result.Wait();
userManager.AddClaimAsync(adminUser.Id, new Claim("Read", "*")).Wait();
userManager.AddClaimAsync(adminUser.Id, new Claim("Create", "*")).Wait();
userManager.AddClaimAsync(adminUser.Id, new Claim("Update", "*")).Wait();
userManager.AddClaimAsync(adminUser.Id, new Claim("Delete", "*")).Wait();
userManager.AddClaimAsync(adminUser.Id, new Claim("UserType", "SuperUser")).Wait();
}
}

Categories

Resources