UAC prompt from an already elevated application - delphi

Let's say an application is already running with elevated privileges.
Is it possible for this application to show a UAC prompt and get its result (successfully confirmed or cancelled)?
Background story: I have an application that requires Administrator privileges but runs in a restricted user account, so an UAC prompt is shown at its start, the user enters Administrator credentials to confirm it and everything works fine. However, for some critical actions I'd like to verify that the current user is (still) allowed to do that.
For example, the original user left the workstation without locking his Windows account (yes, the world's not perfect...) and another user open that already running application and accesses some sensitive settings.
You can compare this to an online-shop, where an already logged in user has to provide his credentials again if he wants to change his delivery address.
I understand that I could create a custom prompt, ask for admin account credentials and check if they're valid, but I don't want to touch those credentials at all. Neither do I want to introduce additional application-specific credentials. The UAC prompt would be a nice and native solution to re-verify the user has admin privileges.
Basically something like this:
if VerifyAdminWithUacPrompt then
begin
//critical stuff
end;
A Delphi example would be perfect, but I'm also happy about general ideas how to accomplish this.

Your app does not need to invoke a new UAC prompt, since UAC is already running your app elevated. The app just needs to ask the user for credentials. Windows has APIs for that very purpose: CredUIPromptForCredentials() and CredUIPromptForWindowsCredentials():
The CredUIPromptForCredentials function creates and displays a configurable dialog box that accepts credentials information from a user.
The CredUIPromptForWindowsCredentials function creates and displays a configurable dialog box that allows users to supply credential information by using any credential provider installed on the local computer.
See Asking the User for Credentials on MSDN for more details:
Your application may need to prompt the user for user name and password information to avoid storing an administrator password or to verify that the token holds the appropriate privileges.
However, simply prompting for credentials may train users to supply those to any random, unidentified dialog box that appears on the screen. The following procedure is recommended to reduce that training effect.
To properly acquire user credentials
Inform the user, by using a message that is clearly part of your application, that they will see a dialog box that requests their user name and password. You can also use the CREDUI_INFO structure on the call to CredUIPromptForCredentials to convey identifying data or a message.
Call CredUIPromptForCredentials. Note that the maximum number of characters specified for user name and password information includes the terminating null character.
Call CredUIParseUserName and CredUIConfirmCredentials to verify that you obtained appropriate credentials.

Related

Should I save passwords in shared web credentials AND (local) keychain

I am in the process to design a login for a new app that will be associated with a domain, i.e. be the counterpart to an SPA.
Obviously I want to use
iOS 11 Password Autofill, and
Shared Web Credentials
I have read the documentation on autofill as well as watched the WWDC video about it. Also, I checked the article on Shared Web credentials, which I think is older than the new, reworked autofill. Said article recommends:
Do not use the shared web credentials as your primary storage for secure user credentials. Instead, save the user’s credentials in the keychain, and only use the shared web credentials when you can’t find the login credentials in the keychain.
This strikes me a little odd, because it
- Means I have to cover more possible inconsistencies, i.e. synchronize the keychain somehow wit the shared web credentials (what if I have credentials in the keychain as well as the shared web credentials, but they're different?)
- Potentially leaves "garbage" behind in the keychain if my user user uninstalls my app (naturally I hope they won't ever do this, but let's be realistic, some will)
Especially the last point had always bothered me in the past (before shared web credentials and autofill were a thing, or when my app doesn't have an associated domain). Unlike on macOS, the iOS Accounts & Passwords feature (in the Settings app) doesn't list ALL passwords, but only the ones used by Safari (i.e. the shared web credentials), correct? Keychain Access on macOS instead offers a means to view and manage all credentials, even those that aren't synchronized over iCloud.
I understand why the same is not offered on iOS, but it also means that for those passwords that my app saves (locally) to "its" keychain "part" can only be managed if I offer a UI for this in my app. And if the user uninstalls the app before using this, the item will stay in the keychain, at least it was that way when I tried it a couple of years ago.
My main question now is, wouldn't it be easier to disregard the article's advice and only rely on the shared web credentials for password storage? That's the part they can edit in Settings (if ever need be) and also it will reflect any password changes done on the website. I would design my app like this then:
First launch: App starts on the Login screen and offers the username/password via Autofill
User logs in: App saves a simple flag in the shared user defaults indicating the user is logged in.
App gets relaunched, e.g. after a device reboot: The app skips the login screen due to the flag and gets the password and user name from the shared web credentials (assuming the user previously granted it permission, of course)
User explicitly logs out: The app deletes the flag, basically setting everything back to first launch
User deletes the username and password from the shared web credentials (e.g. in the Settings app or with Keychain Access on macOS): The app falls back to the login screen as soon as it detects this (e.g. when attempting a remote request, or after relaunch), regardless of the flag. I think this matches the user intention best (if you delete a password you don't want some apps to hold onto it until you log them out)
This setup would avoid any issues with different items in the keychain and shared web storage and it would immediately propagate updates done in the webpage to the app as well (which is what I'd intent for my app anyways). Is there anything that would keep this app flow from working?
(Note: I asked the same question on the apple developer forums, so if you see that as well don't be confused. I will update any potential answers from there to here and vice versa.)
Edit to address #Aaron's answer:
Thank you so much for the info. Your answer helped me realize I misunderstood something about shared web credentials: I assumed that for an app with associated domain, you can access the credentials without user interaction (after perhaps an initial authorization). Like you can set the checkbox on macOS when an application requests credentials. I now realize this is wrong and on iOS you would always have to verify with the user, thanks.
For completeness sake, I still want to point out some of the other things you said:
You are right, we will eventually use token based authentication, so I will save that in the keychain (probably in addition to the password, see below). I just tried to keep the question simple enough at first.
Our app is like an email client where you update new incoming "mail". The mentioned "login flag" in something like the user defaults would thus just indicate whether the app should behave as if subscribed to an inbox or not. Like in Mail, you wouldn't expect to have to login even after relaunch.
For this reason I will probably eventually save the user's password in the (local) keychain along with a token. If the token expires, I can request a new one without user interaction, that's important in our general site and app design. Only if that request fails I would use the shared web credentials (updating my local copy of the creds in the process).
For what it's worth, the last point you mentioned is probably debatable. On macOS, for example (where you can edit the entire keychain, not just Safari passwords) de facto logs you out of an app. Mail, again, as an example. If the keychain item for an inbox is gone, Mail re-asks that the next time it is launched and tries to access the content (effectively a "kind of" login in a way).
Again, thank you a lot for answering, now I can close an open todo. :) Also thanks to #HamZa for giving out a bounty!
Considering this advice:
Do not use the shared web credentials as your primary storage for secure user credentials. Instead, save the user’s credentials in the keychain, and only use the shared web credentials when you can’t find the login credentials in the keychain.
The main issue here is that the shared web credentials process is a little clunky — it requires user interaction and takes time to resolve the credentials. So if the user has already authenticated with your app you want to avoid showing them the login page at all. You can do this by storing credentials in your app's keychain where you can access them immediately without a network connection or user permission.
This doesn't mean you need to store the user's password in the keychain. Typically you would store something like an OAuth access token in the keychain. The presence of this token means the user is authenticated - and if an API endpoint rejects your token then you can take them back to the login page.
This suggestion:
User logs in: App saves a simple flag in the shared user defaults indicating the user is logged in.
is possibly insecure depending on what you're hiding behind the login page, but typically any content belonging to the user should require a valid token to access, not just a bool in the user defaults.
I think this matches the user intention best (if you delete a password you don't want some apps to hold onto it until you log them out)
I disagree with this; I would not expect an iOS app to log out because I deleted a password from my Safari keychain.

Modx Revolution - New user cannot login

I'm trying to create a new user in MODX REVOLUTION 2.3.0 but for some reason, the user cannot access the manager area. I tried to clear every bit of cache as well as to made sure the password is created by the system (email has been sent) and the user belongs to the Users Group.
Strangely, when looking at the user settings, it says that the user has made some 10 logins, but in reality, he has not.
When I type a wrong password, I get the wrong password error message, when I type a correct password, the input field gets cleared and nothing else happens.
Any idea how to solve this?
Thanks.
It seems that user don't have access to mgr context. Any user needs «frames» permission to get access to the manager.
Try to update user's data and make him a sudoer. It'll help to understand if wrong permissions cause the problem.
Exactly. Like #proxyfabio said, he needs access to the manager. To at least asses if the user login works, give him temporary SUDO rights. If that works, work your way from the ground up.
Make sure an Access Policy Template and Access Policy is created. Make sure the policy contains "frames" and is checked at the Policy Template edit screen. Next, PLEASE, make a separate Role, like "Customer". Go into the Aministrator group (or again, PLEASE, create a Customer group) and head on over to the Users tab. Add the User to the group with the Role Customer - "your level" (I usually use increments of 500 or 1000).
Under Context Access, add the user to the mgr context with the specified role and your Customer policy. Do the same for web if you with to avoid any in depth issues.
Finally, save your settings, flush your permissions, clear your cache and optionally flush your sessions table (you can also delete cookies for the browser you're using). When you've done all that, create an Incognito tab in Chrome or Firefox to avoid issues and try the login again.
I have somewhat the same issue if I try login a duplicate manager user from an android phone, the login count goes up, wrong password gives error and correct password just refresh the login page.
However logging in from a computer works. Initially it didn't...
Here are my steps:
Duplicate manager user
Set new password
Login fails
Click forget login for e-mail
Login successfully (computer) with the new generated password
Change original password to original password!? :D
Login works everywhere except my phone

Desire2Learn Revoking User Keys

I am unable to revoke application access by a user via either a password reset or by explicitly clearing app keys in user management. The latter method gives a reply indicating that access has been revoked, but when the user hits the tool, they are not re-prompted to approve access to their information.
There are number of possibilities here:
It's possible that there is latency between the declared revocation of keys and the cleanup task that goes through the database and actually cleans them up; I believe that at one point, such a latency existed, was identified, and fixed through service packs and subsequent releases. Accordingly, you may address this issue by ensuring that your back-end service is up-to-date with its available service packs.
It's possible that what's being revoked is the keys, and the necessity to authenticate to rebuild keys, but not the confirmation step that would appear to the user asking for access permission (assuming the user once authenticated, and checked the "don't prompt me to ask for permission again") dialog.
Can you confirm if the request for user tokens by the client application actually does get back tokens? Or is it just that the authentication step happens with no notice of client confirmation to access?
Note that the re-authentication might appear to happen silently; if the client application's request for user tokens happens through a user's browser context where the back-end service can determine that the user is already logged in to the LMS, then the request for tokens could succeed automatically:
The user is assumed to have already authenticated in order to have an active web session, so there's no need to re-gather a username/password (or whatever user auth step the LMS uses) to re-confirm identity.
The user may already have confirmed access for the application and dismissed the confirmation step with "don't ask me again". If the user has confirmed access with "don't ask me again" this choice will get remembered, even if the user tokens get expired due to password change or access revocation by an admin.
If you explicitly log a user out of their LMS session, and then test the client app, this should indicate to you visibly whether the re-authentication step is actually taking place (the user's browser will then get directed to the login process for the back-end service).
Note that, although a user password change or access revocation by an admin can remove the recorded user Id/Key pair associated with an application, it does not remove the record of the confirmation form having been dismissed with "don't ask again". Currently our system does not expose a way to reset that confirmation state.
If after considering these points you feel you still have an issue, I would encourage you to open a support incident through your organization's approved support contact, or your account or partner manager. Desire2Learn takes security related reports quite seriously, and if you've uncovered an issue that hasn't yet been addressed, I would encourage you to report it as a defect.

How do I better control how DotNetOpenAuth uses Microsoft Account (Live ID)?

I am using the new OAuthWebSecurity wrapper for DotNetOpenAuth to allow users to log in to an MVC4 application with their Microsoft Account (aka Windows Live ID).
I have registered the microsoft client:
OAuthWebSecurity.RegisterMicrosoftClient(clientId: "...", clientSecret: "...");
It is all working, and I love the simplicity of it. But how do I refine what it's doing?
After selecting to log in with their Microsoft Account, the user is taken to a screen asking them to log in:
When they log in, I want them to be able to check the "keep me signed in" box.
Microsoft then asks for them to OK my access:
But I don't actually want that much access. All I want is their name and email address. And maybe their picture. I certainly don't need or want access to their contacts and friends. This is going to scare off my users.
Where can I pass parameters to OAuthWebSecurity or DotNetOpenAuth to control this?
So the user clicks yes and all is ok. However, when they leave and come back to my site - the "keep me signed in" option should have been honored. It isn't. Instead, they see this:
I don't understand the message that says:
Because you're accessing sensitive info, you need to verify your password.
What sensitive info? The contacts/friends I didn't want to begin with? Or something else?
How can I get around these two issues to make my application more user-friendly?
You need to pass the scopes you want, you can just use wl.signin which will sign users into your application if they are already signed in to live without asking for the credentials again.
Check http://msdn.microsoft.com/en-us/library/live/hh243646.aspx

Running application as windows service

I have an application that is running as window service and its running under a valid use account not under default system account ,now my worry is if in future use changes his password for that account will it effect this service??
Thanks
The service will stop working as the user credentials don't match.
Yes.
The password you enter in the service properties must be changed of the user changes his password, so it's a bad idea to run a service under a real live user account.
You can either set it to run on a system account, and grant that account the necessary resources for the service to function, or you can create a pseudo-system account - a user account that is restricted from everything else, except from the service resources.
Yes, if the password is changed for the user account, you need to update the stored password as well.
And to make this answer more programming related, this MSDN article shows you how to do it programmatically: Changing the Password on a Service's User Account

Resources