Strange behavoir of RunWithElevatedPrivileges in Console Aplication with FBA - sharepoint

I have a named site collection where FBA is on und i use ActiveDirectoryMembershipProvider.
We have a farm administrator domain\administrator. He is not explicitly sitecollection administrator.
I created a sample console application that I run under the domain\administrator account.
In the code is something like that:
using (SPSite site = new SPSite(serverUrl))
{
using (SPWeb web = site.OpenWeb())
{
Console.WriteLine(web.CurrentUser.LoginName);
Console.WriteLine(WindowsIdentity.GetCurrent().Name);
string userName = "domain\\testuser";
SPUser spUser = web.EnsureUser(userName);
SPGroup group = web.SiteGroups["GroupName"];
group.AddUser(spUser);
group.Update();
}
}
The console output is domain\administrator however I become an AccessDenied exception when I try to add user to the group.
However when I run this with RunWithElevetadPrivileges (which according to all posts I read should have no influence in console app) and set AllowUnsafeUpdates = true (the same story) the code goes smoothly through, no exception thrown and the user is added to the group. The interesting thing is that the user that is written to the console output is still domain\administrator.
So my question is: WTF? Is there a better way? Why is this happenning? Has anyone already had this problem? Should I use another membershipprovider?
Small hint: When the FBA is off I become no exceptions.

RunWithElevatedPrivileges runs code with permissions of user that the application pool runs. It can be other than Administrator. Are you sure you get the same result with RunWithElevatedPrivileges?
Anyway, a better, more reliable way of elevating privileges is to pass system users User token in SPSite constructor. Try it.

Related

UserCustomAction does not fire for non-tenant admin in SharePoint online

I have written a fairly straight-forward JavaScript for SharePoint Online that I am deploying as a user custom action into the root site collection using CSOM.
The following code is the block I am using for provisioning the script to the site collection:
public static void ProvisionScriptLinkCustomAction(ClientContext ctx, string name, string url)
{
Site site = ctx.Site;
ctx.Load(site.UserCustomActions);
ctx.ExecuteQuery();
foreach (UserCustomAction action in site.UserCustomActions)
{
if (action.Name == name)
{
action.DeleteObject();
break;
}
}
ctx.ExecuteQuery();
UserCustomAction customAction = site.UserCustomActions.Add();
customAction.Location = "ScriptLink";
customAction.Name = name;
customAction.ScriptSrc = url + "?" + Guid.NewGuid().ToString();
customAction.Update();
ctx.ExecuteQuery();
}
I am logged in as the tenant administrator when deploying and initially testing the custom action. Everything works as expected until I log in as a user that is not the tenant admin. When logged in as any other user that is only a site collection administrator or lower, the custom action does not fire and all of my efforts are for naught.
This feels like a configuration or permissions issue to me but I am at a loss to begin to know where to look to rectify this issue.
Any helpful thoughts would be greatly appreciated!
Turns out I had console.log calls in my JavaScript. Some versions of IE apparently do not know how to log to the console when in browser mode without debug tools which presumably throws an uncaught and unlogged exception. Removing the console.log statements made the issue go away.

SharePoint session persist across several users?

I have a custom web part that starts by getting a current user login name like this:
protected static string iAm = System.Web.HttpContext.Current.Request.ServerVariables["AUTH_USER"].Split("\\".ToCharArray())[1].ToLower().
Then it passes this string to a bbl class and fetches a user id:
`IDataReader _drInfo = cisf_BLL.bll_MyInfo.drGetMyInfo(iAm);
while (_drInfo.Read())
{
iUser_Ident = _drInfo.GetInt32(30);
}
`After that it passes the user id integer to another method that fetches user's training record:
_drUserTraining = bll_Training.drGet_required_training_records(iUser_Ident);
_drUserTrainingCompleted = bll_Training.drGet_completed_training_records(iUser_Ident);
This information is then displayed in a tab container with three tab such as "Overdue", "Required", and "Completed".
The problem I'm having is this: I'm logged into SharePoint collaboration site with my domain user name and all my training is displayed just fine. If my someone else then logs in to the SP Portal that user sees my training and not his, even though this user has logged in with his unique credential using a common access card, just as I.
Somehow some strange session seems to persist and I was hoping someone out here has encountered this anomaly.
Thanks in advance!
Risho
You are misusing static - a static property is stored once per web server process, not once per user.
Not an answer, but code improvement: there is much simplyer way to get current user name/id
SPUser user = Microsoft.SharePoint.[SPContext][1].Current.Web.CurrentUser;
user.ID;
user.Email;
user.Name
user.LoginName;
user.Grups;
....
http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spuser_members.aspx

How to use a logged in person's credentials to search Active Directory?

I have a web app (.NET 3.5) which is sending notifications by email to users. In order to do this, I search Active Directory to find each person's email.
At the moment, I am hardcoding my own username and password like so in order to search AD:
Dim entry As New DirectoryEntry("LDAP://companyad", "myUsername", "myPassword", AuthenticationTypes.Secure)
Dim srch As New DirectorySearcher(entry)
srch.Filter = [String].Format("(&(objectClass=person)(sAMAccountName={0}))", "someOtherUsername")
Dim result As SearchResult = srch.FindOne()
Now, obviously, this is not ideal and I don't want those credentials hardcoded. My web app is using Windows Authentication. It also uses impersonation (as the logged in user) to access files and SQL Server. Is there also a way for me to "impersonate" the logged in user in order to search AD?
EDIT 1
I thought I'd better explain why I chose this answer. The problem turned out to not be the multi-hop issue or kerberos as it seems I have set these up correctly.
I had recently changed my app to only allow access to a certain group through the web.config settings. I had previously been only allowing access to myself. I set up the group and added myself to it. I then removed the hardcoded credentials and attempted to run the app WITHOUT RESTARTING my computer.
According to my network admin, I would not be logged on under that new group until I restarted my computer which I think is what was causing my problem. So, Preet's answer is actually the most accurate as I just needed to pass the LDAP path to DirectoryEntry.
EDIT 2
I also needed to register a Service Principal Name.
I ran this:
setspn -A HTTP/[dns name of the site] [machine name]
on my development machine.
Thanks to everyone else for their answers.
Doesn't
Dim entry As New DirectoryEntry("LDAP://companyad")
work?
Why not create a new user for this purpose alone? A user with only searching rights.
I set <identity impersonate="true"/> in my web.config and added the following code to my my page load event handler. It worked fine. Are you sure you are not dealing with a multi hop situation? In that case your app pool account needs to be configured for kerberos authentication to support impersonation in a multihop scenario. More info on this is here: http://support.microsoft.com/kb/329986
Response.Write(User.Identity.Name);
DirectoryEntry entry = new DirectoryEntry("LDAP://[mydomain.net]");
DirectorySearcher srch = new DirectorySearcher(entry);
srch.Filter = string.Format("(&(objectClass=person)(sAMAccountName={0}))", "[user]");
SearchResult result = srch.FindOne();
Response.Write(result.Path);
If you wish to use the Windows logged in user account as the credentials against AD, you have to use the following:
public bool IsExistingUser() {
DirectoryEntry de = new DirectoryEntry(Environment.UserDomainName)
DirectorySearcher ds = new DirectorySearcher(de)
ds.Filter = string.Format("((objectClass=user)(SAMAccountName={0}))", Environment.UserName)
try
SearchResult sr = ds.FindOne();
if (sr != null && sr.DirectoryEntry.Name.Contains(Environment.UserName))
return true;
catch (DirectoryServicesCOMException ex)
catch (COMException ex)
throw new Exception("Can't find logged in user in AD", ex);
return false;
}
Assuming this code would compile and run, it will verify whether the existing logged in user is known by your Domain Controller.
Impersonation is discouraged as it lets litteral password strings travel in your network. So, try to avoid it as much as possible.
EDIT Here's a pretty useful link for AD: Howto: (Almost) Everything In Active Directory via C# I found this post awesome!

Reset page library permission for anonymouse user in SharePoint

In the Site Collection level there is a Page library, which has been created along with the whole site. I didn't touch it for long time until recently I added new content types, modified some page layouts and master pages using a solution file. When accessing the home page using the site configured for anonymouse user it failed with "401 UNAUTHORIZED" error on the web page. I noticed the URL was /_layouts/AccessDenied.aspx?Source=...&Type=list&name={...} Then I copy this string to the site for authenticated user, it appears as "Error: Access Denied". I also checked the guid of name={...}. It's the page library list ID.
It seemed the page library permission is not correctly set. However the other page libraries of sub sites are all working well under anonymous user, using the same new content type, master page and page layouts. Their permission are identical on the settings page (all inherit from parent) and all have "allow anonymous" enabled.
I also tried create pages with other page layouts in that page library, clean up content types, all didn't help.
It's not the permission issue of the page library, rather it is related to the code I modified. SPContext.Current.Site.RootWeb is the the refernce by anonymous user. That user do not have privilege to access root folder. I assumed that SPContext.Current.Site.RootWeb.RootFolder.WelcomePage would work with elevated privilege, but after some reading I realized it's not elevate the privilege as I thought. Here's an explanation.
bool rtn = false;
SPWeb rootWeb = SPContext.Current.Site.RootWeb;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite(rootWeb.Site.Url))
{
using (SPWeb web = site.OpenWeb())
{
rtn = web.Url + "/" + web.RootFolder.WelcomePage
== this.Page.Request.Url.AbsoluteUri;
}
}
});
return rtn;

SPContext.Current.Web.CurrentUser returns misleading value

I'm trying to find out current user name for my sharepoint application. There are more that one way how to do this. However the sharepoint way returns misleading value.
System.Security.Principal.WindowsIdentity.GetCurrent().Name // returns MY_COMPUTER\\my_user
HttpContext.Current.User.Identity.Name // returns MY_COMPUTER\\my_user
HttpContext.Current.Request.ServerVariables["AUTH_USER"] // returns MY_COMPUTER\\my_user
Microsoft.SharePoint.SPContext.Current.Web.CurrentUser.LoginName // returns SHAREPOINT\\system
What is the cause of this behavior? Will I encounter problems if I'll use non-sharepoint way?
Are you browsing as the admin account that you used to install the system? SharePoint will "helpfully" rename that SHAREPOINT\System. Use a different account and all of the methods will return the same value.
This is expected if the user is the application pool account running the current web application.
BTW, it's supposed to be the same name as displayed in the welcome control (upper left control)
The problem is because you are probably getting the current user from an elevated SPWeb inside a RunWithElevatedPrivileges code. You can use the snippet below to get the real user
SPWeb site = SPContext.Current.Web;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite ElevatedsiteColl = new SPSite(siteColl.ID))
{
using (SPWeb ElevatedSite = ElevatedsiteColl.OpenWeb(site.ID))
{
string currUser = site.CurrentUser; //not the ElevatedSite.CurrentUser
}
}
});
This will show the real user name instead of the SHAREPOINT\System user.
I think you might have include this code under SPSecurity.RunWithElevatedPriviliges. Check it out once. I am not sure though
The other way SPWeb.CurrentUser could return SHAREPOINT\system is if the web is elevated, though I'm not sure why SPContext.Current would be elevated. On what kind of page are you seeing this behavior?

Resources