Getting samAccountName name in MVC Web App from Azure Active Directory - c#

I have a requirement to get the AD samAccountName in an MVC C# application that's deployed to an Azure Web App.
The app is Windows Authenticated against Azure AD which is synced with our local on premise AD servers using ADConnect.
When we run the Web App locally (Visual Studio 2017), the value that's returned from:
User.Identity.Name
is returned in the format DOMAIN\UserName
But when looking at the WebApp in Azure, the same code returns it in the format firstname.lastname#domain.co.uk
I appreciate that we won't be able to use User.Identity.Name to achieve a consistent result, but we do need a way of getting this information when the site is running Azure.
We've looked various ways of achieving this using Claims Descriptions and Extended Properties but have had no luck so far.
I've tried to give as much information as possible, but I'm working in conjunction with our infrastructure team so may not have provided enough, please let me know if more info is required.

The "firstname.lastname#domain.co.uk" format would be the userPrincipalName attribute of the account. So if you see an "#" in the name, you can connect to AD and search for the account and pull the sAMAccountName. Something like this:
var searcher =
new DirectorySearcher(
new DirectoryEntry("LDAP://domain.co.uk"),
$"(&(objectClass=user)(userPrincipalName={User.Identity.Name}))");
searcher.PropertiesToLoad.Add("sAMAccountName");
var result = searcher.FindOne();
var sAmAccountName = result.Properties["sAMAccountName"][0] as string;

Related

Matching current user with ActiveDirectory DirectoryEntry

My scenario:
A client app (Net Core WPF) should somehow find out the current user's identity (for example using System.Security.Principal.WindowsIdentity.GetCurrent()) and authenticate with a REST server application (Net Core) which has access to AD (it knows the address, name and password of root AD DirectoryEntry). The authentication should be successful if and only if the user from the client app is found among users in AD. This is an intranet setup btw.
Solutions to similar questions here on SO (for example How to get the current user's Active Directory details in C#) generally propose using DirectorySearcher and filtering on user name "(sAMAccountName=theUserIWantToMatch)".
But IMHO this is not sufficient:
1) It is not secure enough, you can easily impersonate anybody just by creating a user with a similar name. Not to mention man-in-the-middle attacks.
2) It needn't even be malicious, plenty of people have similar names. I might have connected to the intranet network via VPN using a computer with a similar user name (similar to somebody else already on that network).
Can you think of a better way to match the users (using some GUID or token for example) or completely different authentication method? Just to reiterate: I can't use usual ASP.NET windows auth because my client is a WPF app that communicates with the server using HttpClient instance.
Thank you.
A fail-proof way of getting the exact user that's logged in is by using the SID, which is available from WindowsIdentity.GetCurrent().User.
From there, you can bind directly to the AD object using the LDAP SID binding syntax of LDAP://<SID=XXXXX>.
That will look something like this:
var sid = WindowsIdentity.GetCurrent().User;
var currentUser = new DirectoryEntry($"LDAP://<SID={sid}>");
If the computer you're running this from is not joined to the same domain as the user (or trusted domain), then you will need to include the domain name in the LDAP path:
var currentUser = new DirectoryEntry($"LDAP://example.com/<SID={sid}>");
This method is also faster than any other method, since you're not performing a search and then binding to the object. It's all done in one network request.

Check if username exist in Microsoft Azure Active Directory

I am using Microsoft Azure Active Directory login for my MVC 5 application. Can somebody give me an idea how I can check if a username already exists in Microsoft Azure Active Directory?
What is the general approach to do this?
You can use the Graph API and query for the user you want. For information about Graph API read: http://msdn.microsoft.com/en-us/library/azure/hh974476.aspx
The common queries page (http://msdn.microsoft.com/en-us/library/azure/jj126255.aspx) has a query for a user given the userPrincipalName. You should use this query and check if it returns a 404 (not found).
Basically the query you are looking for is: "https://graph.windows.net/contoso.com/users/admin#contoso.com?api-version=2013-04-05" where you need to replace contoso.com with your domain and admin#contoso.com with the upn you want to search for.
You should also look at the Azure AD samples on GitHub. In this case, you're probably interested in how to use the Graph API: https://github.com/AzureADSamples/WebApp-GraphAPI-DotNet
This sample MVC web application demonstrates how to query Azure Active Directory using the Graph API. To facilitate application development, it includes showing how to use included Graph Library, and uses OpenID Connect to authorize users to conenct to their directory data.
An alternative solution :
public async Task<User> FindByAlias(string alias, GraphServiceClient graphClient)
{
List<QueryOption> queryOptions = new List<QueryOption>
{
new QueryOption("$filter", $#"mailNickname eq '{alias}'")
};
var userResult = await graphClient.Users.Request(queryOptions).GetAsync();
if (userResult.Count != 1) throw new ApplicationException($"Unable to find a user with the alias {alias}");
return userResult[0];
}

Get system logged in username in c# that also works in IIS

I thought its simple to get the logged in username, in fact, it works fine with most of the responses available on stack overflow but when I publish the website all method fails.
Can anybody please guide me to get the name of the logged in user from Windows with following condition.
I just need logged in user name so forget about AD when you write the response.
I cannot change to Windows authentication mode because user may be a guest user who is not part of company but still have access to my intranet website
it’s not possible to change the user browser setting as there are more than 6000 users
I cannot disable the anonymous authentication as I want everyone to be able to use the website
I have already tried following solution and all works fine when I run the website on debug mode but all fails to return the username when I publish the website on IIS so please help me with some new as solution
string _windowLogonUserName = System.Environment.UserName.ToString()
string _windowLogonUserName =
WindowsIdentity.GetCurrent().Name.Remove(0, _adDomainName.Length + 1)
string _windowLogonUserName =
System.Web.HttpContext.Current.User.Identity.Name.ToString();
System.Security.Principal.WindowsIdentity.GetCurrent().Name;
AppDomain appDomain = Thread.GetDomain();
appDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
WindowsPrincipal windowsPrincipal = (WindowsPrincipal)Thread.CurrentPrincipal;
Logger.Write("username principal" + windowsPrincipal.Identity.Name);
Request.ServerVariables["LOGON_USER"]
It sounds like you're publishing the site outside of the AD domain. if the server is not on the domain, it won't be able to authenticate (or even accept) Windows users. The basic answer is that you can't get it.
If the server is internal (on the domain) then you can enabled integrated windows auth in IIS. Here's a reference.

User Permission Mask from NetworkCredentials

Although I am currently developing this WinForms application on our Sharepoint server I intend for the finished program to function from any computer on the Domain. I'm using the WSS web services to get all the information I use from Sharepoint.
I have written some code which will check Sharepoint Permission masks, with logical OR against mask, for all the permissions it covers but I am having trouble returning the Sharepoint mask for the current user. I would like users to be able to log right in through Windows Authentication so this was my immediate idea.
NetworkCredential credentails = CredentialCache.DefaultNetworkCredentials;
var userInfo = userGroupService.GetUserInfo(credentails.UserName);
However although I am able to return the permission collection for the entire Sharepoint site with DefaultNetworkCredentials (as in bellow snippet) the properties are empty strings, so I can't use it to get the UserName.
permissionService.Credentials = CredentialCache.DefaultNetworkCredentials;
permissionService.Url = "http://localhost/mySite/_vti_bin/Permissions.asmx";
// Web service request works
XmlNode node = permissionService.GetPermissionCollection(siteName, "Web");
// But I need to identify current user from this collection somehow still
I read that Windows Authentication suffers from a double-hop issue, which I want to avoid, but as I am developing on the server Sharepoint & IIS are running, I can't see this causing an immediate issue.
Is there a way around this or a better way to get the current users permission mask?
If the current user for wss will always be the same as the user currently logged on to the pc
var userInfo = userGroupService.GetUserInfo(Environment.UserDomainName +#"\"+ Environment.UserName);
or to get the permissions for the currently logged on user
XmlNode currentUserPermission = userGroupService.GetRolesAndPermissionsForCurrentUser();
You are dealing with an issue where the authentication cannot move beyond one remote host; this is known as the "one-hop" limitation.
To overcome this, you have to get into "Constrained Delegation," where a computer/account are expressly authorized to receive and accept authentication credentials from another computer/account. This is set up in Active Directory by defining the appropriate Service Principal Names (SPN's) on either "end" of the delegation.
You can get more details about Constrained Delegation here.
Good luck! CD can be a bit of a pain to set up, so tread carefully.

Trouble getting test user information

I'm trying to use the Facebook SDK 5.2.1 to ultimately create a test user, however even what I believe is the simple example of getting the list of test accounts isn't working for me. I get the OAuthException "An access token is required to request this resource."
Here's my code (replace APP ID and APP SECRET with my own):
FacebookOAuthClient oauth = new FacebookOAuthClient { AppId = "APP ID", AppSecret = "APP SECRET" };
dynamic tokenRes = oauth.GetApplicationAccessToken();
fbClient = new FacebookClient(tokenRes.access_token);
dynamic response = fbClient.Get("APPID/accounts/test-users");
However, I get the exception on the fbClient.Get line.
Any idea as to what's wrong?
Thanks,
Chad
After hours of trying various things and reading various web pages/blogs, I found the reason it wasn't working. In my app settings, I had my app type set to a Native/Desktop App. Changing this to Web, allows the above scenario to work. I'm not yet quite sure of what other differences exist between web vs native facebook apps. My app is certainly only being used via a desktop application and I can't understand why I need to set this to Web just to allow me to create test users.
This code works in my app:
var app = new FacebookClient(FacebookApplication.Current.AppId,
FacebookApplication.Current.AppSecret);
dynamic result = app.Post(string.Format("{0}/accounts/test-users",
FacebookApplication.Current.AppId),
new { installed = true, permissions = "user_about_me" });
The reason why you are receiving the exception OAuthException is because you have not yet got the permission of the user.
To do a Graph API call on the current user, you need to get the user to accept the permissions that you require FIRST and then do the Graph API call.
You need to get the user to a browser some how in your application, as there is not an authentication flow which doesn't require a browser window.
Check out this URL to view the authentication flows:
http://developers.facebook.com/docs/authentication/

Categories

Resources