I'm trying to understand better how Windows sessions work, so if I have some weird mistakes in the question, please, let me know.
I use LsaEnumerateLogonSessions() to get all the logged on sessions in the system.
Now I have LUID that represents a log-on, and if I understand correctly, it represents a user that logged on or a build it user like SYSTEM.
Now, if user X starts a process, Windows gives that process a token that represents X.
Is there a way (in a Windows service) to get the user's token from LUID?
I know I can get it from a process HANDLE, but that is not what I want.
You can use LsaGetLogonSessionData to get the session id and then use WTSQueryUserToken to get the token from that. Note that you may need to run as LocalSystem for WTSQueryUserToken (see "How can I get the current user token for the physical session?" regarding that).
Related
I am using
WTSEnumerateSessionsEx(WTS_CURRENT_SERVER_HANDLE, &level, 0, &pSessionInfo, &count);
to get session information. It will tell me all logged in users. If I use it on Windows 11 with another user logged in,
WTS User: DESKTOP-VVVVVVV\joew, session id: 1, state: 0, session name: Console
WTS User: AzureAD\JoeWillcoxso_garbage, session id: 17, state: 4
From the state, joew is the active user and JoeWillcoxso_garbage. It's not exactly that, but I'm protecting it...you get the idea.
The session info will give me the domain and username. When I login to Windows for an AzureAD with a non-standard credential provider, I use my AzureAD email address and the CP is smart enough to use AzureAD as the domain name. But, when the machine was joined to AzureAD, it created a local account for the email address as JoeWillcoxso_garbage. ( I write "created a local account", but in PowerShell if I do get-localuser *, that user does not show up in the list.)
I can use LsaEnumerateLogonSessions() and LsaGetLogonSessionData() to get session data from the local security authority. I can match things between the two calls (LsaGetLogonSessionData and WTSEnumerateSessionsEx) using session id and username. However, there is no way to get an email address. I can get a PSID in the session data, not sure if there is a way to turn that into an email address. On my local machine, I'm not attached to an AD. Just running as WORKGROUP.
For an AzureAD user, calling NetUserGetInfo() always fails for the AAD user even when running elevated. I haven't yet tried as NT_AUTHORITY account...
I'm looking for an API or maybe some way to query WMI to turn the AzureAD\JoeWillcoxso_garbage user name into joe#someaad.onmicrosoft.com email address. Or, maybe need a web API to hit login.windows.net. There are places in the registry where I can find the email address, but I don't think they are guaranteed to always be there.
Since a user may be logged in already (and on Windows 10/11 with fast switching), sometimes an unlock is not CPUS_UNLOCK_WORKSTATION but CPUS_LOGON. With fast switching, if I lock, come back 10 minutes later, and do an unlock, it's not an unlock but a logon (CPUS_LOGON) although it acts just like an unlock used to do.
For instance, at HKEY_USERS\THE_SID_OF_THE USER\Software\Microsoft\Office\Teams, HomeUserUpn has the email address. I can get the SID of the logged on users...so I could possible get the email to match up... but, that's assuming that key is there. I want something more bullet proof.
• You can surely get the email address from the UPN for the signed in user through the below powershell commands very easily as you must have remote script execution rights over the systems in your network.
a) Whoami /upn --> Displays the full email address of the logged in user
b) "$env:USERNAME#$env:USERDNSDOMAIN" --> Displays the full email address along with the DNS zone in which its entry is mapped to
c) $msAccountName = ([adsisearcher]"(samaccountname=$env:USERNAME)").FindOne().Properties.mail
$msAccountName --> Displays the email address from the online O365/Azure AD account
Thus, accordingly as per the above powershell commands, you can get the email address of the logged in session user for Azure AD. Also, if you want to use the WTS query function for this purpose, kindly refer to the below link for more details as it aptly describes the usage of WTS query commands for the said purpose: -
https://www.idrix.fr/Root/Samples/upn.cpp
I wanted something to use from Win32, hence the tag. What I did find is that from a process running as NT_System account, I could iterate all the LSA sessions.
I could use LSAEnumerateLogonSessions() to get a list of all the sessions.
Once I had the sessions, for each session I could call LsaGetLogonSessionData() which would return a PSECURITY_LOGON_SESSION_DATA which importantly returns session ID, logon domain, logon name, and SID of the user. Looking at the logon domain, I could know if it was AzureAD because it would literally be AzureAD. Knowing it was AzureAD, I could then use the SID and do a registry lookup at key (not entire function):
CString s;
s.Format(L"SOFTWARE\\Microsoft\\IdentityStore\\Cache\\%s\\IdentityCache\\%s", lpwzSid, lpwzSid);
ATL::CRegKey regKey;
if (ERROR_SUCCESS == regKey.Open(HKEY_LOCAL_MACHINE, s, KEY_READ))
{
WCHAR szUserName[MAX_PATH] = { 0 };
ULONG ulChars = MAX_PATH;
if (ERROR_SUCCESS == regKey.QueryStringValue(L"UserName", szUserName, &ulChars) && ulChars > 0)
{
return CString(szUserName);
}
}
That almost works except for one little nit... sometimes the AzureAD user has logged out but still has an open LSA session. I have no idea how this happens, but I have observed it on Windows 11. IDK if this is for all AzureAD users, but I have noticed it can be the case for the account used to join the AzureAD domain. So, in that case, it is necessary to backcheck and use WTSEnumerateSessionsEx() and verify that there really is an open session.
I'm trying to determine the logon session ID for a particular user process. To do this, I've retrieved the process token and then called GetTokenInformation with the TokenOrigin option.
However, the answer always seems to be 0x3E7, even if I have two different users logged in simultaneously. Obviously that can't be right.
What is TokenOrigin actually looking up, and what is the significance of 0x3E7 in particular? How do I get the real logon session ID for a token?
The documentation for TOKEN_INFORMATION_CLASS, under TokenOrigin, says:
If the token resulted from a logon that used explicit credentials, such as passing a name, domain, and password to the LogonUser function, then the TOKEN_ORIGIN structure will contain the ID of the logon session that created it.
That kind of sounds as if it means the logon session that the token belongs to, but if you read it carefully it could equally well mean the logon session associated with the process that performed the authentication operation, and it turns out that is indeed what is returned. In Windows 7, 0x3E7 is usually the logon session of winlogon.exe which is responsible for authenticating interactive logons.
If we look under logon identifier in the glossary it says:
To retrieve the logon ID from an access token, call the GetTokenInformation function for TokenStatistics; the logon ID is in the AuthenticationId member.
I have confirmed that this works as expected.
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.
Customer want to restrict duplicate login for the App, once user login from another phone, the session of previous phone should be invalidated.
but I can't find the API for worklight to do this, besides using push, another suggestions? thank you very much.
Worklight indeed does not provide any API for this type of scenario.
Here is what I am thinking as an example of what can be done:
Device #1 is an Asus, device #2 is an LG
As the user log-ins, you will store the device information in the Worklight database (using WL.Client.setUserPref)
When the user will try to log-in again from another device, you could pull the existing pref (using WL.Client.getUserPref) and compare the device types
If they are not the same, logout current userId and re-login
(Consult the user documentation for additional API methods around userpref)
This could be a way to ensure the user is logged only from one device.
You could also use the userId associated with the deviceId and update upon every login if (currentDeviceId != latestDeviceId) logout(); and so on...
Here I have posted a implementation mechanism which strikes in my mind.
Its still a suggestion.
Whenever a user tries to login an entry can be made in backend[DB/Webserice] which tells about the user/device information.
If the user info is existing already then you can prompt a dialog box to the user The account has been logged in already, if you continue to login the previous session would be logged out trigger a push notification to the previously logged in user device, if user continues.
Now a notification will be reached to previously logged in device. Here you can implement the logic to execute the WL.Client.logout(realm, options).
It would be great if someone post answer better than what I did.
And also let me know if my suggestion was helpful or not.
A session token is given to the user when he starts running a facebook application, as long as this token is not stolen, other people cannot impersonate him. To increase security, a new token is also generated again when it has expired or has been cleared.
So what is the problem here? Why do people want infinite session token in facebook?
How is it useful to both developers and end-users of facebook applications?
It's now called "offline_access". You're right in that most applications don't need this permission; however, occasionally an app may want to do some processing on behalf of the user while the user isn't present. For example, there are some blogging apps like posterous.com that allow you to email your blog posts - and they may want to publish without asking each time. For those, it's appropriate to ask for the extended perm.
Here's more information about how to request the permission:
https://developers.facebook.com/docs/guides/policy/examples_and_explanations/Extended_Permissions/
Why do people want infinite session
token in facebook?
So that when they exit their browser and restart it, they don't have to type in the username and password again. The authentication is still there so they can just simply start facebooking.