How in mvc 5 I can found out role of logged user?
I made the user by this code
private bool AddUserAndRole()
{
IdentityResult ir;
var rm = new RoleManager<IdentityRole>
(new RoleStore<IdentityRole>(new ApplicationDbContext()));
ir = rm.Create(new IdentityRole("admin"));
var user = new ApplicationUser() { UserName = "Admin" };
var result = UserManager.Create(user, "somepassword");
UserManager.AddToRole(user.Id, "admin");
return true;
}
After I loggin on site by that user. How in controller I can check if that user have role == "admin" or not? I found only one way which doesnt look works fast.
var rm = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new ApplicationDbContext()));
var role = rm.FindByName("admin");
bool result = User.IsInRole(role.Name); //true
Do we have other ways?
bool result = User.IsInRole("admin")
Much easier. :)
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
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.
In the last few days I have been working on integrating Umbraco Backoffice with IdentityServer v3. I have managed to get to the point, where I authenticate user externally and have Umbraco create a user with some default user type in the backoffice and link it to the external account.
The next thing I'm doing is updating the Umbraco user type, based on the roles of the user. I think I found a way of doing that on linking the Umbraco to the external account, but I cannot see any way to constantly update the user types with each login, in case the roles were removed/added for a user.
By analyzing the code in Umbraco BackOfficeController, it seems there is no way to get into the process of authenticating and update data on the side of Umbraco.
var user = await UserManager.FindAsync(loginInfo.Login);
if (user != null)
{
await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
}
else
{
if (await AutoLinkAndSignInExternalAccount(loginInfo) == false)
{
ViewBag.ExternalSignInError = new[] { "The requested provider (" + loginInfo.Login.LoginProvider + ") has not been linked to to an account" };
}
}
It seems that if the umbraco login is found, then the user is just being logged in, without any exposed events or options. Only if the user is not found, then the whole process of creation and linking is started, where I could actually make some changes to the user properties.
That said, is there any way to actually update the user types of an Umbraco user, based on the claims from external server, on every login?
My code from the Startup class is below.
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie
});
var idAuth = new OpenIdConnectAuthenticationOptions
{
Authority = "https://localhost:44332",
ClientId = "id",
ClientSecret = "secret",
RedirectUri = "http://localhost:8081/Umbraco",
ResponseType = "id_token token",
Scope = "openid profile roles email",
Caption = "test",
SignInAsAuthenticationType = Umbraco.Core.Constants.Security.BackOfficeExternalAuthenticationType
};
idAuth.Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = async n =>
{
var id = n.AuthenticationTicket.Identity;
var givenName = id.FindFirst(System.Security.Claims.ClaimTypes.GivenName);
var familyName = id.FindFirst(System.Security.Claims.ClaimTypes.Surname);
var roles = id.FindAll(System.Security.Claims.ClaimTypes.Role);
var nid = new ClaimsIdentity(
id.AuthenticationType,
System.Security.Claims.ClaimTypes.GivenName,
System.Security.Claims.ClaimTypes.Role);
nid.AddClaim(givenName);
nid.AddClaim(familyName);
nid.AddClaims(roles);
nid.AddClaim(id.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier));
nid.AddClaim(id.FindFirst(System.Security.Claims.ClaimTypes.Email));
n.AuthenticationTicket = new AuthenticationTicket(
nid,
n.AuthenticationTicket.Properties);
}
};
//idAuth.AuthenticationType = "https://localhost:44332";
idAuth.ForUmbracoBackOffice("btn-google-plus", "fa-google-plus"); //temporary icon/button
idAuth.AuthenticationType = "https://localhost:44332";
var externalOptions = new ExternalSignInAutoLinkOptions(autoLinkExternalAccount: true, defaultUserType: "admin");
//externalOptions.OnAutoLinking; // TODO: set user type based on roles
idAuth.SetExternalSignInAutoLinkOptions(externalOptions);
app.UseOpenIdConnectAuthentication(idAuth);
Managed to solve this some time ago by manually checking the roles claim and Umbraco UserType on SecurityTokenValidated with the help of Umbraco services IExternalLoginService and IUserService. If the combination is not right (e.g. the administrator role is not present in the claim), I use Umbraco IUserService to update that user's UserType
Notifications =
new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = async n =>
{
var id = n.AuthenticationTicket.Identity;
var uid = id.FindFirst(ClaimTypes.NameIdentifier);
var givenName = id.FindFirst(ClaimTypes.GivenName);
var familyName = id.FindFirst(ClaimTypes.Surname);
var roles = id.FindAll(ClaimTypes.Role);
var rolesList = roles as IList<Claim> ?? roles.ToList();
if (
!rolesList.Any(
c =>
string.Equals(c.Value, RoleNames.ContentEditor,
StringComparison.InvariantCultureIgnoreCase)))
throw new HttpException(403,
"You do not have any roles configured for the application");
// create new identity and set name and role claim type
var nid = new ClaimsIdentity(
id.AuthenticationType,
ClaimTypes.GivenName,
ClaimTypes.Role);
UpdateUserType(uid.Value, rolesList, applicationConfiguration.AuthorityUrl);
nid.AddClaim(givenName);
nid.AddClaim(familyName);
nid.AddClaims(rolesList);
nid.AddClaim(uid);
nid.AddClaim(id.FindFirst(ClaimTypes.Email));
n.AuthenticationTicket = new AuthenticationTicket(
nid,
n.AuthenticationTicket.Properties);
}
}
private static void UpdateUserType(string uid, IList<Claim> roles, string providerName)
{
var userService = ApplicationContext.Current.Services.UserService;
var oneUser = ApplicationContext.Current.Services.ExternalLoginService.Find(new UserLoginInfo(providerName, uid)).FirstOrDefault();
if (oneUser == null)
return;
var user = userService.GetUserById(oneUser.UserId);
if (user == null)
return;
if (
roles.Any(
r => string.Equals(r.Value, RoleNames.Administrator, StringComparison.InvariantCultureIgnoreCase))
&& !string.Equals(user.UserType.Alias, UmbracoRoleNames.Administrator))
{
SetUserType(user, UmbracoRoleNames.Administrator, userService);
return;
}
if (
roles.Any(
r => string.Equals(r.Value, RoleNames.ContentEditor, StringComparison.InvariantCultureIgnoreCase))
&& !string.Equals(user.UserType.Alias, UmbracoRoleNames.ContentEditor))
{
SetUserType(user, UmbracoRoleNames.ContentEditor, userService);
return;
}
}
private static void SetUserType(Umbraco.Core.Models.Membership.IUser user, string alias, IUserService userService)
{
try
{
user.UserType = userService.GetUserTypeByAlias(alias);
userService.Save(user);
}
catch (Exception e)
{
LogHelper.Error(typeof(ClassName), "Could not update the UserType of a user.", e);
}
}
In this specific case, I do not change the UserType back to a non-admin/non-content editor one when someone lacks that privilege from their roles claim, because they are being filtered out one step before and a 403 error code is being returned.
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.