Once a IOrganizationService object is instanciated, it´s possible to impersonate?
Better...
How to impersonate a instanciated IOrganizationService object?
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service = serviceFactory.CreateOrganizationService(someUserId);
Related
Today I was configuring authorization provider for Oauth middleware and trying to insert some guid value into Thread.CurrentPrincipal.Identity.Claims. But when I tried to call Thread.CurrentPrincipal's FindFirst I've got nothing.
Here is the example what I was trying to do:
public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var claimsIdentity = Thread.CurrentPrincipal.Identity as ClaimsIdentity;
if (claimsIdentity != null)
claimsIdentity.AddClaim(new Claim("TestClaim", Guid.NewGuid().ToString()));
var claimValue = ((ClaimsPrincipal)Thread.CurrentPrincipal)
.FindFirst(x => x.Type == "TestClaim"); //claimValue == null!
}
Checking inner properties, found that Thread.CurrentPrincipal.Identity still contains claim I've set before, but Thread.CurrentPrincipal.Identities[0] - doesn't. So there are two different identity instances with their own set of claims.
I tried to do the same steps inside Web Api controller's action and there Identity was referencing to Identities[0] which means that there is the same instance.
What is happening to OWIN middleware's Currentprincipal so it's Identity and Identities[0] refer to different instances? Can anyone explain me this, please?
Thank you!
I met the same issue. I don't know why the Identity property and the first identity of the Identities property are different instances...
But it seems that all methods relative to claims in the ClaimsPrincipal class (Claims, FindFirst...) are based on the Identities property, so updating the Identity property has no effect.
I prefer to keep the two identities consistent, so I use the following workaround to solve the problem :
principal = (ClaimsPrincipal)Thread.CurrentPrincipal
identity = (ClaimsIdentity)user.Identity;
identity1 = user.Identities.First();
identity.AddClaim(claim);
identity1.AddClaim(claim);
I'm following this article in which is described how to assign roles to users when theiy log-in using forms authentication:
public void Application_AuthenticateRequest( Object src , EventArgs e )
{
if (!(HttpContext.Current.User == null))
{
if (HttpContext.Current.User.Identity.AuthenticationType == "Forms" )
{
System.Web.Security.FormsIdentity id;
id = (System.Web.Security.FormsIdentity)HttpContext.Current.User.Identity;
String[] myRoles = new String[2];
myRoles[0] = "Manager";
myRoles[1] = "Admin";
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(id,myRoles);
}
}
}
I put the role logic in the event handler, so I basically don't need a role provider. Nonetheless, in order to run this, appears that I must enable Role Provider in web.config. Sadly, if I just put:
<roleManager enabled="true"/>
it results in runtime errors related to a failed connection to the SQL server, like if I chose AspNetSqlRoleProvider as Role Provider.
What should I do to have roles working this way? How can I choose to use no role provider, or how should I implement a dummy one (if it makes any sense)?
You shouldn't need to enable roleManager in web.config - after all, people used to use roles with .NET 1.x before roleManager came along.
One thing that roleManager will do for you that you haven't done in your code is set Thread.CurrentPrincipal to HttpContext.Current.User. If you're relying on this (e.g. using PrincipalPermissionAttribute), then you need to add this:
Thread.CurrentPrincipal = HttpContext.Current.User;
Otherwise, I'd expect it to work: what symptoms are you seeing that makes you think it isn't working?
As for implementing a dummy RoleProvider, it's easy enough: for example see this MSDN article.
You only need to implement the GetRolesForUser and IsInRole methods; the other methods can simply throw NotSupportedException.
Why does the code below work fine when I run my web application localhost but not when I install it to an IIS server?
using (HostingEnvironment.Impersonate())
{
UserPrincipal activeUser = UserPrincipal.Current;
String activeUserSid = activeUser.Sid.ToString();
String activeUserUPN = activeUser.UserPrincipalName;
}
Please don't suggest I stick with HttpContext.Current.User as it doesn't provide access to SID or UPN without additional calls to Active Directory.
The web application will be used by Windows authenticated users from three separate domains, the web server is hosted in a fourth domain. The Application Pool is configured to run under the NetworkService identity and the web app configuration has identity impersonation set to true.
The error message when it runs on IIS is:
Error in Page_Load(): UserPrincipal.Current.
System.InvalidCastException: Unable to cast object of type
'System.DirectoryServices.AccountManagement.GroupPrincipal' to type
'System.DirectoryServices.AccountManagement.UserPrincipal'.
at System.DirectoryServices.AccountManagement.UserPrincipal.FindByIdentity(PrincipalContext
context, IdentityType identityType, String identityValue)
at System.DirectoryServices.AccountManagement.UserPrincipal.get_Current()
at webapp.Details.Default.Page_Load(Object sender, EventArgs e)
EDIT:
Tried both the following and unfortunately get the same error.
UserPrincipal userPrincipal = UserPrincipal.Current;
Response.Write(userPrincipal.Name);
Principal userOrGroup = UserPrincipal.Current;
Response.Write(userOrGroup.Name);
I had a lot of issues deploying UserPrincipal.Current and still don't fully understand why.
I finally ended up using PrincipalSearcher, and created the following function to do what I thought UserPrincipal.Current was doing.
private UserPrincipal GetActiveDirectoryUser(string userName)
{
using(var ctx = new PrincipalContext(ContextType.Domain))
using(var user = new UserPrincipal(ctx) { SamAccountName = userName})
using(var searcher = new PrincipalSearcher(user))
{
return searcher.FindOne() as UserPrincipal;
}
}
And I passed System.Web.HttpContext.Current.User.Identity.Name into that method as the userName.
It seems like need some other method to determine user.
Here description from msdn for property:
"Gets a user principal object that represents the current user under which the thread is running."
So, UserPrincipal.Current returns user under what IIS running.
http://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.userprincipal.aspx
Yes, its because you are disposing of the returned UserPrincipal object due to the multiple using statements. Remove 'ctx' from the using statement, then it becomes the callers responsibility to dispose of the returned object.
I am upgrading a site to use MVC and I am looking for the best way to set up Authentication.
At this point, I have the log-in working off of Active Directory: validating a username and password, and then setting the Auth cookie.
How do I store the user's role information at time of log-in, in order for my controllers to see those roles as the user navigates through the site?
[Authorize(Roles = "admin")]
I have no problem getting a list of roles from Active Directory. I just don't know where to put them so that the controllers will see them.
Roles are added to the IPrincipal of the HttpContext. You can create a GenericPrincipal, parse the list of roles in the constructor and set it as HttpContext.User. The GenericPrincipal will then be accessible through User.IsInRole("role") or the [Authorize(Roles="role")] attribute
One way of doing this (in C#) is to add your roles as a comma separated string in the user data parameter when creating your authentication ticket
string roles = "Admin,Member";
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
1,
userId, //user id
DateTime.Now,
DateTime.Now.AddMinutes(20), // expiry
false, //do not remember
roles,
"/");
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName,
FormsAuthentication.Encrypt(authTicket));
Response.Cookies.Add(cookie);
Then access the role list from the authentication ticket and create a GenericPrincipal from your Global.asax.cs
protected void Application_AuthenticateRequest(Object sender, EventArgs e) {
HttpCookie authCookie =
Context.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null) {
FormsAuthenticationTicket authTicket =
FormsAuthentication.Decrypt(authCookie.Value);
string[] roles = authTicket.UserData.Split(new Char[] { ',' });
GenericPrincipal userPrincipal =
new GenericPrincipal(new GenericIdentity(authTicket.Name),roles);
Context.User = userPrincipal;
}
}
When you authenticate your user, you generate a new GenericPrincipal instance. The constructor takes an array of strings which are the roles for the user. Now set HttpContext.Current.User equal to the generic principal and write the auth cookie, and that should do it.
For those of you using MVC 4 or Greater you will need to take Jaroslaw Waliszko's advice when making use of David Glenn's answer:
"I've tested it in ASP.NET MVC 4 and I suggest to use Application_PostAuthenticateRequest instead. Otherwise the generic principal will be overridden." – Jaroslaw Waliszko Sep 7 at 16:18
So as stated above, all you need to do is replace the Application_AuthenticateRequest method name with Application_PostAuthenticateRequest to get this to work. Worked like a charm for me! If I was allowed to upvote Jaroslaw and David, I would.
I'd be inclined to just create a custom role provider. Example here:
http://www.danharman.net/2011/06/23/asp-net-mvc-3-custom-membership-provider-with-repository-injection/
Could you not drop in either an authorization store role manager or find (e.g. on Codeplex) or write another Role Provider that works with Active Directory to get the groups information?
This would save you the hassle of authenticating the user, getting their roles, and then re-passing that information into the constructor, and would all happen automatically for you as part of the framework.
Is there any good way of combining ASP.NET Windows Authentication with a custom IPrincipal/IIdentity object? I need to store the user's email address and have done so for Forms Authentication using a custom IIdentity/IPrincipal pair that I added to the Context.CurrentUser during the AuthenticateRequest event.
How would I best go by to accomplish this using WindowsAuthentication?
Maybe you could create your "ExtendedWindowsPrincipal" as a derived class based on WindowsPrincipal, and just add your extra data to the derived class?
That way, your ExtendedWindowsPrincipal would still be recognized anywhere where a WindowsPricinpal is needed.
OR: since you're talking about using Windows Authentication, you're probably in a Windows network - is there an Active Directory or a user database somewhere, where you could look up your e-mail address that you're interested in instead of storing it in the principal?
Marc
I ended up refactoring my initial solution into replacing the Principal instead of the Identity as I originally thought. Replacing the Identity proved troublesome, since i ran into security problems when creating an instance of a new extended WindowsPrincipal.
public class ExtendedWindowsPrincipal : WindowsPrincipal
{
private readonly string _email;
public ExtendedWindowsPrincipal(WindowsIdentity ntIdentity,
string email) : base(ntIdentity)
{
_email = email;
}
public string Email
{
get { return _email; }
}
}
In my Authentication module i replaced the principal on the HttpContext like this:
var currentUser = (WindowsIdentity)HttpContext.Current.User.Identity;
HttpContext.Current.User =
new ExtendedWindowsPrincipal(currentUser, userEmail);