I'm trying to use Windows Identity Foundation for authorization in my WPF client/server (WCF) application that may or may not be run in the same trust environment as the active directory that provides authentication. For example, authentication may be provided by the active directory, but the application may run in the cloud and the user's profile roles/permissions for the application will be provided by the application database.
I feel I'm missing a fundamental piece of the WIF process in my head in order to fully understand what I'm supposed to do:
User logs into the Windows domain using an Active Directory Username/Password
The user opens my application.
I reference the WindowsIdentity of the logged in user and can now look at their login token and all their configured roles/claims - but just like they can log into the domain, they could log into their own machine and would still have a WindowsIdentity token.
I can tie the user's Windows Identity to their user profile in my database and grant them access to the specific functionality in my application that their profile allows them to.
The piece I am missing is that I have this WindowsIdentity instance from WindowsIdentity.GetCurrent()... how do I verify what generated this? i.e. Is it a local machine user or an active directory user and if it's an active directory user, how do I know that it's my bona fide active directory server?
For instance - a couple of scenarios:
Scenario 1
The user names their local computer with the same name as my active directory domain
The user creates a local user on that computer with the same username as a user they know exists on my active directory that has full administrative access to my application.
They log into my application and for all intensive purposes they appear to have the same username as if the administrative user had logged onto my active directory.
In this scenario, the user has a local user account and not an active directory account and it has a spoofed identity created to purposefully circumnavigate application security.
I assume that there's some way to determine that this is a Windows Local User account and not an Active Directory user? I could make a call to my active directory for the user account with the username found in the WindowsIdentity and compare the SIDs to determine that this is in fact a spoofed user account and the user should be denied access.
Is this the correct way to do this? Is there some way I can tell from the WindowsIdentity that it was issued by my active directory and that this identity hasn't been tampered with?
Scenario 2
The user creates a spoofed Active Directory server with the same name as my active directory and creates an account mimicking the same process as the local user described in scenario 1.
Now I have an active directory user with the same domain name and username the same solution I suggested for scenario 1 would solve the issue for this scenario as well, but it would again be nice to determine that this token wasn't created by my active directory just by examining the token.
Can someone clear up what I'm missing - or am I missing anything at all? Should I just be making a call to Active Directory to authenticate that the WindowsIdentity provided is allowed access to my application?
Simple answer:
Your active directory is identified by more than just the name. When your computer joins the domain it exchanges a set of credentials. Spoofing an active directory or any other computer is much harder than merely creating a computer with the same name.
Windows takes care of all the behind the scenes authentication between machines. Bugs and vulnerabilities aside you can be pretty sure that when you call WindowsIdentity.GetCurrent() there is an unbroken chain of thrust backed by different credentials to authenticate the user.
More complete answer:
There are two types of windows authentication:
The first type is among peers in a network (i.e. outside of a domain). In this case when a user in computer A is connecting to computer B it's actually using a local user of B. If the user in B happens to have the same name and password as the user in A then the authentication happens without user intervention. If not a login screen appears and the user needs to provide credentials for some user in B. In any case the user is actually loging in to computer B, and B doesn't need to trust or know about the local use in computer A.
The second type is in a domain. I believe you can only add users from a domain if the computer itself is in part of the domain or in a domain with a trust relationship with it. In any case when the computer B will have a different set of credentials which allows it to authenticate the domain controller(s). Now when the user from computer A wants to login computer B asks the domain controller (which it knows and trusts) to authenticate the user. Once it gets the OK from the domain controller the user is accepted.
Windows supports various protocols for authentication some newer and more robust than others. The network administrator configures which protocols are accepted. Most (all?) protocols do not involve sending the actual password over the network (look at digest authentication for an example of such a protocol or read about the old NTLM protocols)
Related
I have some code that should run in a console application and does some initialization for the users. The code is in dot net core 3.1 and I need to get the current user's email out from the environment to do the task. How do I do it?
From the Environment I see that I can access the UserName, but that is basically the person's Name.
Environment.UserName
Any suggestions?
Update 1
The assumption is that the users are logged in to Windows/Mac with their Azure Active Directory user and therefore have all necessary data which is email in here.
Update 2
The az login is the first action before running the app. Can we take anything out of that token?
Preface: This answer assumes familiarity with OIDC, the structure of a JWT, and that you know the differences and responsibilities of access_token and id_token.
This answer is based on this blog post: https://mikhail.io/2019/07/how-azure-cli-manages-access-tokens/
When a user runs az login and the OIDC authentication flow is successful, then the Azure CLI (az) will save the current credential state to disk at ~/.azure/. As of March 2020, the az executable does not attempt to encrypt or otherwise protect its cached OIDC tokens from other user processes (for better or for worse) - in this case it's a good thing - provided you don't mind malware easily nabbing your credentials.
The user's e-mail address (at least, their e-mail address associated with their AzureAD account) will be inside their OIDC identity token JWT (id_token) - this doesn't seem to be cached by az login so you'll need to use an OIDC client to use the plaintext access_token extracted from the ~/.azure/accessTokens.json file to request the OIDC userinfo (User Profile Resource) from AzureAD's OIDC service (assuming the access_token grants you access to the User Profile Resource in the first place).
But assuming you do have access to the User Profile Resource, the user's e-mail address will be in the email claim property.
You cannot get the current operating system's user's e-mail because it isn't defined.
I think you're referring to UPN-style usernames as seen in Windows Active Directory domains which are of the form {userName}#{fqdn}, e.g. alice#corp.bob.com (where corp.bob.com is the fully-qualified Active Directory domain name). A UPN is often, but not always, a user's e-mail address because of Microsoft Exchange Server's default configuration.
...but UPNs don't exist on platforms that don't use Active Directory, such as embedded systems and most Linux installations. You'd have to use the LDAP library in System.EnterpriseServices to look it up (perhaps using ADSI).
I need to create a web-api which should authenticate a user through active directory . The api should be available publicly and need to authenticate the users which is inside a intranet. But the user authentication should also be done from outside the particular intranet. What should i do to open service avail publically
It's not secure to Authenticate external users against your production Active Directory directly. But that doesn't mean you can't accomplish your task. You should start looking into Active Directory Lightweight Directory Services
AD LDS or formerly known as ADAM will allow you to authenticate external users against your Active Directory using Proxy Authentication.
What Is Proxy Authentication?
Proxy authentication allows a user to perform a simple bind to an AD LDS instance, while still maintaining an association to an Active Directory account. Two accounts are involved in the transaction. The first is a special object in AD LDS called a userProxy object. The second is the user's account in Active Directory.
The AD LDS userProxy object is a representation of the Active Directory account. The proxy object is tied to the Active Directory account through that account's security identifier (SID). There is no password stored on the actual proxy object itself.
When a user performs a simple bind to an LDS instance with a proxy object, the bind is redirected to Active Directory by passing the SID and password to a domain controller. The AD LDS server performs the authentication, and the entire process is invisible to the end user
You can not authenticate users with AD outside your intranet. They should use an VPN connection to gain access to your network before been authenticated.
I am new to Active Directory and was given a task to fix a bug where a app on one of our servers could not access active directory on another server. The user we are using to bind to active directory is a "Domain Admin" and we are using this user's credentials in a C# application to access active directory with the System.DirectoryServices.AccountManagent classes of .net 3.5.
The server is in the same domain as the active directory server.
After struggling to make the app work, the network administrator set up trust (as a last resort) to the server computer (where the app is installed) and that allowed the app to work.
The network admin said :
"If I open the computer account in AD and click on Delegation (and then select 'Trust this computer for delegation to any service (Kerberos only)' it works!! I can't see why I should need to enable delegation for the server as it's already on the domain anyhow - but it works"
My question is why was this necessary?
It sounds like a programming error where PrincipalContext isn't taking effect. None of these samples change the default service context... If he looks at the event logs he probably sees MachineName$ (dollar sign) logging in.
Try this - Set the service account name from LocalService to the account you want to use with LDAP. It should work, even without domain admin rights.
I am working on a C# Asp.net site that adds users to Active Directory and assigns them to security groups.
The whole script works great except for one issue. I can add users to groups, but I get an "Access Denied" exception when trying to add the user to a group that the Application Pool's Identity is a member of.
I think it's a windows permissions issue, but I'm not sure what permission is required. We had the same issue in the past when using an older VB script.
Any ideas?
I had this kind of issue with a website designed for active directory management. The execution environment was not allowed to manage AD so far. So, through IIS, we changed the default account to local system, who has full permission (almost, he can't reboot the system for example) and cannot be logged (security first). This works for you are impersonating your website.
If not, You will need an advanced group and user management. AD permissions are very touchy.
Edit:
In your case, using a specific account is not a problem. Check the identity when your admin logs, and use impersonation with Local System. Your application environment will be alright, and only your admin will have an access.
I am writing a ClickOnce WPF app that will sometimes be used over VPN. The app uses resources available only to domain authenticated users. Some of the things include accessing SSRS Reports, accessing LDAP to lookup user information, hitting web services, etc.
When a user logs in from a machine that is not authenticated on the domain, I need to somehow get his credentials, authenticate him on the domain, and store his credentials.
What is the recommended approach for
authenticating domain users over
VPN?
How can I securely store the credentials?
I've found several articles but, not much posted recently and a lot of the solutions seem kinda hacky, or aren't very secure (ie - storing strings clear text in memory).
It would be cool if I could use the ActiveDicrtoryMembershipProvider, but that seems to be geared for use in web apps.
EDIT:
The above is kind of a workaround. The user must enter their domain credentials to authenticate on the VPN. It would be ideal to access the credentials the user has already entered to login to the VPN instead of the WindowsIdentity.GetCurrent() (which returns the user logged into the computer). Any ideas on how that could work? We use Juniper Networks to connect to the VPN.
Answer
I ended up doing basically what was suggested in the link below. When the app starts, I'll detect whether the user is on the domain. If so, I'll use those credentials when calling services. If the user is on the VPN (but not on a domain authenticated machine), I prompt for the user's credentials and authenticate via System.DirectoryServices. If the user gives valid credentials I'll store the domain, user and password in a SecureString. The app then uses that information to create credentials to pass to various services.
Thanks!
This answer to the question might help.
--EDIT--
If the client is logging under their AD credentials then WindowsIdentity.GetCurrent() would return a valid WindowsIdentity.
If client is not logged onto the domain then you can provide a pop up that would ask for AD credentials.
Well, just thinking...