Once a user is logged into a Windows-Authentication site, how do I get their Active Directoy user guid from the User.
Eg in an Action:
ViewBag.Message = User.Identity.GUID????
You should check out the System.DirectoryServices.AccountManagement (S.DS.AM) namespace. Read all about it here:
Managing Directory Security Principals in the .NET Framework 3.5
MSDN docs on System.DirectoryServices.AccountManagement
Basically, you can define a domain context and easily find users and/or groups in AD:
// set up domain context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
// find the current user
UserPrincipal user = UserPrincipal.Current;
if(user != null)
{
// get guid
var userGuid = user.Guid;
}
The new S.DS.AM makes it really easy to play around with users and groups in AD!
string userName = user.Identity.Name.Split('\\')[1];
using (var oRoot = new DirectoryEntry(ConfigurationManager.AppSettings["LDAPDomain"], null, null, AuthenticationTypes.Secure))
{
using (var deSearch = new DirectorySearcher(oRoot))
{
deSearch.Filter = string.Format("(&(sAMAccountName={0}))", userName);
SearchResult searchResult = deSearch.FindOne();
if (searchResult != null)
{
DirectoryEntry de = searchResult.GetDirectoryEntry();
}
}
}
Related
My goal is to check if user is member of specific active directory group.
In .net mvc i was using this code inside my service
HttpContext.Current.Request.LogonUserIdentity.Groups
.Any(x => x.Translate(typeof(NTAccount)).Value == "some role"
and it worked well.
In .net core mvc 2.1.2 i pass IHttpContextAccessor into service constructor and try to use following
_httpAccessor.HttpContext.User.Identity.LogonUserIdentity.Groups
but there is an issue, because Identity does not contains LogonUserIdentity. I tried to find any solution but i was not successful, how can i get the list of user groups or check if user is member of specific one ?
Except using built-in function which check the permission by "Roles", if you want to check by specific AD Group, you can also use below codes :
public static class Security
{
public static bool IsInGroup(this ClaimsPrincipal User, string GroupName)
{
var groups = new List<string>();
var wi = (WindowsIdentity)User.Identity;
if (wi.Groups != null)
{
foreach (var group in wi.Groups)
{
try
{
groups.Add(group.Translate(typeof(NTAccount)).ToString());
}
catch (Exception)
{
// ignored
}
}
return groups.Contains(GroupName);
}
return false;
}
}
And using as:
if (User.IsInGroup("GroupName"))
{
}
I have the following table
Permissions Table
On login, I am getting the values of ProductEdit, ProductView, ProductDelete for that logged in user and storing them in session to be used later for custom authorization on some actions within the project. This is achived with the following code (note var permissionJoin)
if (usr != null)
{
Session["OperatorId"] = usr.OperatorId.ToString();
Session["Username"] = usr.Username.ToString();
Session["GroupId"] = usr.GroupId.ToString();
var permissionsJoin = from up in db.UserPermissions
join op in db.Operators
on up.GroupId equals usr.GroupId
select new UserPermissionData
{ UserGroupId = up.GroupId, P_Edit = up.ProductEdit, P_Create = up.ProductCreate, P_Delete = up.ProductDelete };
Session["ProductPermission"] = permissionsJoin.ToList<UserPermissionData>();
return RedirectToAction("LoggedIn");
}
I am using a named class [UserPermissionData - that has the four properties I need] to store these values. The results are getting stored in the session fine.
Now onto my authorization class were I need to extract those values and check - if the user has the permission for a particular. I have the following code
public class AuthorizeProductEdit : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
//lets get the session values of the current user's permissions
var userP = (UserPermissionData)HttpContext.Current.Session["ProductPermission"];
var editProduct = userP.P_Edit;
if (editProduct.ToString() == "Y")
{
return true;
}
else
{
return false;
}
}
}
at the point of clicking an edit action for the logged in user I am getting an "Unable to cast object of type" error [see image]
Error Image
How can I cast back that query to be able to use if for checking my permissions.
You store in Session is a List<UserPermissionData> so you must cast session value to List<UserPermissionData>
var userP = HttpContext.Current.Session["ProductPermission"] as List<UserPermissionData>;
if (userP == null) return false;
return userP.Any(x => x.P_Edit.ToString() == "Y");
I want to create web portal, where there will be multiple users of 3-4 types. So I have created roles in Startup.cs Like
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
createRolesandUsers();
}
// In this method we will create default User & roles
private void createRolesandUsers()
{
ApplicationDbContext context = new ApplicationDbContext();
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
if (!roleManager.RoleExists("Admin"))
{
var role = new Microsoft.AspNet.Identity.EntityFramework.IdentityRole();
role.Name = "Admin";
roleManager.Create(role);
var user = new ApplicationUser();
user.UserName = "1";
user.Email = "a#b.com";
user.ScreenName = "Ra";
user.UserType = "Admin";
string userPWD = "1";
var chkUser = UserManager.Create(user, userPWD);
if (chkUser.Succeeded)
{
var result1 = UserManager.AddToRole(user.Id, "Investor");
}
}
It creates Usertypes and on login page I give radio button to select own type.
Now, suppose there are 4 roles.
Admin
Player
Coach
And suppose 10 people signup to site
2 people as admin
4 people as player
4 people as coach.
Now each one has it's type and user id. And if they log in, they can't access controllers of each other due to Autorize attribute. But my question is, what about 4 players? Will they be ever able to access each others account?
They have same authorize rights and they are authenticate too. How can I prevent users from same type to access each other's account ?
I use " User.Identity.GetUserId() " on each page to get current user and I log all transactions by current id.
I have an mvc project with database first entityframework. In Project I have 3 tables.
Users >>> UsersInRoles <<< Roles with many to many relationship.
and my CreateUser codes below;
public bool CreateUser(string email, string password, string birthday,string firstname,string lastname)
{
bool result;
var dogumgunu = Convert.ToDateTime(birthday);
var sifre = FormsAuthentication.HashPasswordForStoringInConfigFile(password, "sha1");
var confirmation = CreateConfirmationToken(email);
try
{
var user = new User
{
UserName = email,
Password = sifre,
UserJoinDate = DateTime.Now,
UserBirthDay = dogumgunu,
UserConfirmationToken = confirmation,
UserID = Guid.NewGuid(),
MemberFirstName = firstname,
MemberLastName = lastname
};
var role = new Role
{
RoleName = "Client"
};
user.Roles.Add(role); //problem is here!!!!!!!!!
_bb.Users.AddObject(user);
_bb.SaveChanges();
result = true;
}
catch (Exception)
{
result = false;
}
return result;
}
In this code I am new user creating. And I am adding a role. But This code include a new Role in Roles table. I dont want to this. I want to just add UsersInRoles table a new user. What is wrong? Thanks for reply.
Swap these two lines:
_bb.Users.AddObject(user);
user.Roles.Add(role);
because AddObject converts the whole object graph to the Added state. If you add the role afterwards, its state will remain Unchanged.
And you should fetch the role from the database first or create a Role object that only has an existing RoleId. (A so called stub entity).
So in stead of new Role you could do
var role = _bb.Roles.Single(r => r.RoleName == "Client");
I have an MVC3 application and I would like to give the users the ability to set preferences that would be enabled when the user logs in.
I really don't have any idea where to start with this and would really appreciate being pointed in the right direction. I did try some changes to the membership class but now I am thinking that's probably not the best way to go about things.
You could do it in a database (sounds like you might be using one at least with the out-of-the-box membership provider) once uniquely identifying a user. In that case, you may want to implement your own membership provider.
You have to do a little work to start implementing your own provider. If this is your only requirement, you might be able to avoid it by writing your own class that returns settings in a format of your choosing
public static class UserSettings
{
public static string GetSettings(IPrincipal user)
{
if(user.Identity.IsAuthenticated)
{
// dip into database using user.Identity.Name property
return "string with user settings";
// this also assumes user.Identity.Name is uniquely able
// to identify a user in your database!
}
return string.Empty;
}
}
Or, if the information is completely trivial, maybe you could implement a cookie representation of the user settings. This, of course, comes with all the caveats of using cookies, but you could avoid storing the information in a database
Anywhere you have an HttpContext you could grab the settings value like so:
if(HttpContext.Current != null)
{
string userSettings = HttpRequest.Current.Request.Cookies["NameOfCookie"];
}
You can use the FormsAuthentication cookie to store your user information and avoid accessing the database all the time. That cookie is encrypted and whatever information you're storing as safe as the user session itself. The only problem with the cookies is that they have a maximum size of 4K so, if your user info is massive then you might run into a problem. When I use the cookie approach I store my user data as a JSON and then deserialize that JSON on each page request. Here is my login controller logic (I'm using SimpleMembership but the approach is the same:
public ActionResult Login(LoginModel model, string returnUrl)
{
if (ModelState.IsValid && WebSecurity.Login(model.UserName, model.Password, model.RememberMe))
{
var authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
if (authTicket != null)
{
var user = _userLogic.GetItem(model.UserName);
if (user != null && user.IsActive)
{
var newAuthTicket = new FormsAuthenticationTicket(authTicket.Version, authTicket.Name, authTicket.IssueDate, authTicket.Expiration, authTicket.IsPersistent, JsonConvert.SerializeObject(user));
var newCookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(newAuthTicket))
{
Expires = authCookie.Expires
};
Response.Cookies.Add(newCookie);
return RedirectToLocal(returnUrl);
}
WebSecurity.Logout();
ModelState.AddModelError("UserName", "This account has been deactivated.");
return View(model);
}
}
}
// If we got this far, something failed, redisplay form
ModelState.AddModelError("", "The user name or password provided is incorrect.");
return View(model);
}
Notice the newAuthTicket creation and how user instance is passed to it as a JSON. After that all I have to do is desirialize this user object in my base controller's OnAuthorization method:
protected override void OnAuthorization(AuthorizationContext filterContext)
{
var authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
if (authTicket != null)
{
var principal = new CustomPrincipal(HttpContext.User.Identity)
{
CurrentUserInfo = JsonConvert.DeserializeObject<User>(authTicket.UserData)
};
HttpContext.User = principal;
AppUser = principal.CurrentUserInfo;
ViewBag.AppUser = AppUser;
}
}
base.OnAuthorization(filterContext);
}
Create a new table in your database.