I've been developing an application that uses SSPI for Client / Server authentication. Everything works fine, but still one question remains.
The first argument of SspiPromptForCredentials is the target name... But what is it really used for?
I can literally put anything as a target name, my code will work. I don't even see it written anywhere (in the GUI).
Is it related to the authentication method? I use Negotiate.
Thanks for your help :)
I think it might be related to how the credentials are saved in the credential manager.
The only SspiPromptForCredentials example I can find on MSDN just uses a simple useless string ("Target").
For CredUIConfirmCredentials MSDN says:
Pointer to a null-terminated string that contains the name of the target for the credentials, typically a domain or server application name.
This must be the same value passed as pszTargetName to CredUIPromptForCredentials or CredUICmdLinePromptForCredentials
CredUICmdLinePromptForCredentials has a similar parameter and for this MSDN says:
A pointer to a null-terminated string that contains the name of the target for the credentials, typically a server name.
The pszTargetName parameter is used to identify the target information and is used to store and retrieve the credential.
...
Credentials are stored in the credential manager based on target name. Each target name is stored as generally as possible without colliding with credentials already stored in the credential manager. An important effect of storing credentials by target name is that a particular user can have only one credential per target stored in the credential manager.
These other CredUI functions are perhaps lower-level but I think the parameter usage is the same.
MSDN says this about Negotiate:
To allow Negotiate to select the Kerberos security provider, the client application must provide a service principal name (SPN), a user principal name (UPN), or a NetBIOS account name as the target name. Otherwise, Negotiate always selects the NTLM security provider.
The answer is a little more benign than you might think. SSPI supports arbitrary credential types, so the API needs to provide a way to prompt for credentials that a particular SSP understands without having to expose a 3rd party API. You can't launch a UI from within the SSP itself because it runs in LSA, so there's an implicit contract between the app builder and the SSP builder that if you need special credentials you're going to have to call SspiPromptForCredentials.
In some cases it's possible that SSP you're trying to use might require knowledge of the target to form the shape of the marshaled credential. Often times it doesn't.
Negotiate just happens to not require that information because the credentials you enter are not dependent on the target.
Related
EDIT:
Thank you #RbMm for your clarification questions!
I am implementing MFA in a credential provider (not a wrapper provider). One of the options I must support is to verify the same UPN is used for logging in to the computer and validating with the MFA provider. I use LsaLogonUser, ImpersonateLoggedOnUser and GetUserNameEx(UserNamePrincipal) to obtain this information. This works in most environments; however, on a computer connected to a hybrid Azure AD domain, LsaLogonUser fails. This lead to an investigation the results of which are elaborated below:
I have a computer belonging to an AzureAD hybrid domain, but I have no way of getting the SAM-compatible domain name from the AzureAD domain name.
For example,
I can log in with a user whose AzureAD upn is, for example's sake user#domain.com. The SAM-compatible name is localdomain\localuser.
GetUserNameEx(NameUserPrincipal) reutrns user#domain.com
GetUserNameEx(NameSamCompatible) returns localdomain\localuser
HOWEVER in the following code, TranslateName fails with GetLastError() returning ERROR_NO_SUCH_DOMAIN.
TCHAR validBuffer[MAX_PATH+1];
ULONG nValidSize = MAX_PATH;
TranslateName("user#domain.com", NameUserPrincipal, NameSamCompatible, validBuffer, &nValidSize);
I have also tried the following APIs without success, they all fail with different return values:
GetComputerObjectName fails with any value passed to NameFormat
GetCompterNameEx fails with ERROR_CANT_ACCESS_DOMAIN_INFO for any relevant value of NameType
NetWkstaGetInfo does not return any useful information in any field
Also, if you look at the computer's join information in This PC > Properties > Advanced System Properties, u see it as part of a workgroup, not a domain.
-if you run the dsregcmd /status command:
executed within the aforementioned user's logon session: the 'Diagnostic' part lists the localdomain in the output
executed from a command prompt running with the LocalSystem account, the output does not list the localdomain anywhere.
An important point (thanks #RbMm) - the code services a Windows Credential Provider, when using the 'Other User' tile. I am trying to pre-verify the entered credentials using LsaLogonUser, before serializing them successfully in my implementation of ICredentialProviderCredential2::GetSerialization. Using 'user#domain.com' fails, while using 'localdomain\user#domain.com' or 'localdomain\localuser' succeeds. When logging in with Windows' built in password provider, using 'user#domain.com' of course works. Maybe I should be using a different authentication package for LsaLogonUser?
I am STUMPED.
thanks for anyone's help..
Uriel
Client sends username and password to the server.
Server then checks if this user is authenticated.
If yes, the server returns an access token for the client...
Then user can use this access token to access protected resources...
The advantage here, is that we are not sending user info via API calls, and the access token will not last for long time, so hackers won't be able to find out user authentication info (user name and password), and if he finds out, the access token won't last long enough to do anything with it.
That's how I understand Laravel passport API security.
The confusing thing here, is that on first API call, user has to send user name and password, so hacker still have big chance to find out user info!!!
I know that there is something wrong with my understanding, and that's why I get confused, any explanation would be very appreciated.
There must be a way to prove your identity to authorization server, and one way is to provide username and password. The way you're gonna achieve communication between authorization server and your client application is totally up to you as long as it uses HTTP. As stated in RFC-6749:
This specification is designed for use with HTTP ([RFC2616]). The
use of OAuth over any protocol other than HTTP is out of scope.
Of course it's always advised to use HTTPS whenever possible. Just because HTTP is mentioned in document, doesn't mean HTTPS cannot be used because HTTPS is just encrypted version of HTTP.
Other thing I wanted to mention is that you don't need to provide username and password, there are several grant types where you can, for example, instead of username and password you can provide client_id and client_secret which is used in Client Credentials grant type.
If you are new to this I believe this all is little bit confusing for you. To summarize the purpose of OAuth2 to you (as far as I get it), is:
To separate role of the client (which can be browser, mobile etc.) from the resource owner (usually the owner of account). Why? Because if there is no separation, the client has access to user's sensitive data.
Imagine that the first point is secure enough for communication. But what happens if someone gets their hands on the session you have? They have access to all! This is why OAuth introduces scopes, where depending on the scope user has with provided access token has limited access to resources. Scope can be read, write, share etc. - this implementation is up to developer. So if someone gets their hands on your access token, because of scope they only have a limited access to resource.
These are one of my reasons, while RFC-6749 has better explanation:
Third-party applications are required to store the resource
owner's credentials for future use, typically a password in
clear-text.
Servers are required to support password authentication, despite
the security weaknesses inherent in passwords.
Third-party applications gain overly broad access to the resource
owner's protected resources, leaving resource owners without any
ability to restrict duration or access to a limited subset of
resources.
Resource owners cannot revoke access to an individual third party
without revoking access to all third parties, and must do so by
changing the third party's password.
Compromise of any third-party application results in compromise of
the end-user's password and all of the data protected by that
password.
To learn more about OAuth2, it's grant types and purposes, I recommend you to read this:
An Introduction to OAuth 2
Mentioned RFC-6749, even though it can be difficult to read because of technical writing.
Hope I clarified at least a small piece of blur.
ADFS 2016 supports a new claim type "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsdevicegroup" which contains the Windows devices group SIDs. How may I cast the claims on a simple claims aware ASP.Net Application ? I am on VS 2015, .Net 4.6. What are the minimum requirements to grab this claim type and its value from ADFS so I may use it. Any code snippet would be highly appreciated.
I need help in getting the code that can do something like this but for a Windows Device -
ClaimType - http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsdevicegroup , ClaimValue - S-1-21-5-xxxx-xyyyy-zzzzzz.
Where S-1-21-5-xxxx-xyyyy-zzzzzz is the SID of a Group the computer is member of.
Also, Any chance that this claim type may be used with ADFS 2012R2 ?
This uses the compound authentication pattern that was released as part of WS2012 Active Directory. See https://www.microsoft.com/en-us/download/confirmation.aspx?id=36830 for details on it. Look for the compound authentication section. Then you need to pass the necessary claims by modifying the ADFS's claims provider trust for "Active Directory". Now you have those claims that can be consumed by a downstream application.
Note that this works through Kerberos. So, only if the client is inside the corporate network with line of sight to the a correctly enabled domain controller, will this use case light up.
Thanks
//Sam (#MrADFS)
We have an windows app that runs as an Administrative account but we need to determine the access rights to files and directories of a particular user that is logged in to the app.
One solution we have used is to use the user name only to generate an access mask:
BuildTrusteeWithName(&trustee, username);
GetEffectiveRightsFromAcl(pSecurityInfo->pAcl, &trustee, pAccessMask);
The problem with this is that it takes quite a long time on some customer sites with complex DFS setups. We believe the time is taken in looking up the user's groups etc...
So another solution we have used is to cache the user name and password to 'impersonate' the user, temporarily caching a handle to the 'impersonation' token:
// Here we get the handle to the 'impersonation' token
LogonUser(owner, NULL, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, pTempHandle);
DuplicateToken( *pTempHandle, DEFAULT_IMPERSONATION_LEVEL, pOwnerHandleCacheEntry->pHandle );
// This is then called for all files and directories traversed. pOwnerHandle is the handle of the 'impersonation' token obtained above.
// This means the overhead of getting the user's groups etc... is only done once.
AccessCheck(pSd, *pOwnerHandle, MAXIMUM_ALLOWED, &genericMapping, &privilegeSet, &dwPrivSetSize, &fileAccessMask, &accessStatus);
The problem with this is if we wish to introduce Single Sign On, we don't have access to the user's password. This will leave some sites that wish to use SSO with a system that doesn't perform very well as they will need to switch back to first solution (above).
So, my questions are:
1) Is there a way of caching the user information used to build the access rights using just the user name (in order to avoid doing lookups every time) ?
2) Failing question 1 (above), is there an equivalent of our preferred solution within an SSO environment (for example: impersonating a user using a kerberos ticket)?
Roughly speaking, the SSO equivalent of LogonUser is SSPI. SSPI allows a server to authenticate a client without needing the client's password. After successfully authenticating the client, the server will have access to a user token, but as with everything in SSPI it's complicated how to get it. From there, you can call AccessCheck which should be very fast.
I am front-ending an app with Shibboleth authentication. How can I retrieve the authenticated username in order to display it in my app?
You need to have that attribute released to you. Typically it will be added as a header to the request by the local SP, at least that's the way it works on IIS with the ISAPI extension.
You can access the Attributes in a manner specific to your application's language and environment. The preferred method is to use environment variables, but you can also use HTTP request headers, which can have some security issues because clients can "fake" whatever headers they want (however, some HTTP front-ends like nginx will drop headers that have underscores in them, which is what the Shibboleth Native SP would typically use).
If you're using Java on Tomcat, for example, you would have mod_proxy_ajp on Apache HTTP working with mod_shib2, and you would configure the SP to prepend "AJP_" to the header/variables so that the mod_proxy_ajp code puts those on the Request as Attributes instead of Headers.
Anyway, once you know that the username (possibly the Principal/Subject) is being passed to your application, you can simply access it via the typical Attribute access methods for your programming language as noted in the link above.
eduPerson Object Class Specification (200806)
2.2.8. eduPersonPrincipalName (defined in eduPerson 1.0); OID: 1.3.6.1.4.1.5923.1.1.1.6
RFC 4512 definition
( 1.3.6.1.4.1.5923.1.1.1.6
NAME 'eduPersonPrincipalName'
DESC 'eduPerson per Internet2 and EDUCAUSE'
EQUALITY caseIgnoreMatch
SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
Application utility class: standard; # of values: single
Definition
The "NetID" of the person for the purposes of inter-institutional authentication. It should be represented in the form "user#scope" where scope defines a local security domain. Multiple "#" signs are not recommended, but in any case, the first occurrence of the "#" sign starting from the left is to be taken as the delimiter between components. Thus, user identifier is to the left, security domain to the right of the first "#". This parsing rule conforms to the POSIX "greedy" disambiguation method in regular expression processing. When the scope is a registered domain name, the corresponding registrant organization is to be taken as the scope. For example, francis#trinity.edu would imply that the identity behind the ePPN has the "NetID" "francis" at the instituion of higher education that registered itself with the domain name "trinity.edu." If other value styles are used, their semantics will have to be profiled by the parties involved. Each value of scope defines a namespace within which the assigned principal names are unique. Given this rule, no pair of eduPersonPrincipalName values should clash. If they are the same, they refer to the same principal within the same administrative domain.
Notes
If populated, the user should be able to authenticate with this identifier, using locally operated services. Local authentication systems should be able to adequately affirm (to both local and remote applications) that the authenticated principal is the person to whom this identifier was issued.
The initial intent is to use this attribute within the Shibboleth project, http://shibboleth.internet2.edu/. However, it has quickly become clear that a number of other applications could also make good use of this attribute (e.g. H.323 video, chat software, etc). eduPersonPrincipalName (EPPN) would be used as follows: A resource owner, A, would look at B's directory entry to discover B's EPPN. A would then tell the local authorization system that B's EPPN is allowed to use the resource. When B tries to access the resource, the application (or access control infrastructure) would validate B's identity, check with the local authorization system to ensure that B has been granted the appropriate access privileges, and then either grant or deny access.
EPPN looks like a Kerberos identifier (principal#realm). A site might choose to locally implement EPPN as Kerberos principals. However, this is not a requirement. A site can choose to do authentication in any way that is locally acceptable.
Likewise, EPPN should NOT be confused with the user's published email address, although the two values may be the same. Some sites have chosen to make the user portion of email addresses and security principals the same character string; other sites have chosen not to do this. Even when they appear to be the same, they are used in different subsystems and for different purposes, and there is no requirement that they have to remain the same.
The uid attribute of the user's object within the local white pages directory may also contain a login id, a security principal; some systems (eg NDS) may put a login id in the cn attribute. These attributes are defined within objectclasses that are universal. Unfortunately, their use is not prescribed in a sufficiently precise and consistent manner for use with cross domain authorization. A variety of systems already make conflicting use of these attributes; consequently, we have defined this new attribute.
An assumption is that EPPNs are managed on an enterprise basis by the univ of univ.edu. A particular EPPN is assigned solely to the associated user; it is not a security principal identifier shared by more than one person. Lastly, each EPPN is unique within the local security domain.
How long, if ever, before a formerly assigned EPPN is reassigned to a differrent individual is an institutional decision. Some institutions will choose never to reassign EPPNs. Others may opt for a relatively short hiatus before reassignment. While this complicates the work of the relying parties, it is unavoidable given institutional autonomy. See MACE best practice documents on identifiers for further discussion of these issues.
This attribute should prove useful in creating some applications that are based on currently deployed technologies and on code that does not currently use LDAP or require a PKI. This attribute should help to create a framework to foster interesting inter-institutional collaborations between sites that use different technologies. In short, this attribute provides a foundation for yet another abstraction layer.
Example applications for which this attribute would be useful
controlling access to resources
Example (LDIF Fragment)
eduPersonPrincipalName: hputter#hsww.wiz
Syntax: directoryString; Indexing: pres,eq,sub
References:
http://middleware.internet2.edu/eduperson/docs/internet2-mace-dir-eduperson-200806.html#eduPersonPrincipalName