Here is a snippet I have in use for a long time now …
property KeychainPasswordName : "YOUR_KEYCHAIN_PASSWORD" -- name of your password item in the Keychain
set my_password to getPassword(KeychainPasswordName)
set my_username to getUsername()
-- Retrieve the administror password you saved on your Keychain
on getPassword(keychainItemName)
local password
set password to do shell script ("/usr/bin/security 2>&1 >/dev/null find-generic-password -gl " & quoted form of keychainItemName & " | cut -c 11-99 | sed 's/\"//g'")
if password contains "could not be found in the keychain" or password as string is equal to "" then
display alert "Password not found in the keychain" message "Certain tasks in this script need the administrator password to work.
You must create a new password in the OS X Keychain with a custom name, and set it with your administrator password, then edit this script." as critical
error "Password could not be found in the keychain."
else
return password
end if
end getPassword
-- Get the short username (name of your home folder)
on getUsername()
#tell application "System Events" to return the name of current user
short user name of (system info)
end getUsername
as far as I am aware this code works without issues…
Is there a way to just request access to the human’s “user name” & “password” which will likely be an Administrator username/password for the Mac ?
It’s easy enough to tell the user to create a new entry in Keychain Access for my Applet so it can know what the user name and password of an admin account is, but there’s going to be that percentage that just can’t do it right, and so the Applet won’t work as expected…
ps: the getUsername function needs a small correction
– Get the short username (name of your home folder)
on getUsername()
# tell application “System Events” to return the name of current user
return short user name of (system info) ## Added the return
end getUsername
However, the frameworks used are from 2015/16 and therefore do not run on an Apple Silicon. Perhaps someone could recompile them (unfortunately I failed).
About the SSKeychain Framework- it might be unmaintained but I can confirm that it is still usable with Monterey on an Intel Processor based Mac.
I have to say thank you to you as well - if you’ve not posted in your blog about these two Frameworks - we might possibly never known about their existence. Thank you
Why has no one suggested using the excellent “Usable Keychain Scripting” app written by Daniel Jalkut, of Red Sweater and FastScripts fame?
Though written in 2006, it still works fine here. But then, I am still running Big Sur. Can’t swear it works on later macOS versions. To try it, grab it here: Usable Keychain Scripting –
StanC, wouldn’t I have to bundle “Usable Keychain Scripting” with my Applet though, if I used “Usable Keychain Scripting” and manage to give away at least one copy of my Applet ??
The bit about “personal needs” may rule out giving away or selling it bundled in your software. However, the intent of the word “personal” is not clear. Maybe Daniel himself could clarify?
Which leads inevitably to the larger problem of a moribund language abandoned by those in control of the system of which it’s an almost completely neglected part.
So many of the technical discussions here can be regarded as details of the decline and fall of macOS automation. Forgive the digression, but has any organized group ever make a serious attempt to address the larger problem? AppleScript has been in conspicuous decline for more years than I can easily recall.
The question of keychain access has nothing to do with AppleScript and whether the language is maintained or not!
I have posted a Sample above with which you can create, read and delete a keychain entry with applescript. You can also access other entries for which the process has access:
set keychain to current application's DTKeychain's sharedInstance()
set query to current application's DTKeychainGenericPassword's keychainItemQueryForService:(missing value) account:(missing value)
set {itemList, errorRes} to my (keychain's keychainItemsMatchingQuery:query |error|:(reference))
repeat with i from 0 to (itemList's |count|()) - 1
set theItem to (itemList's objectAtIndex:i)
try
log ("Service name: " & theItem's service as text) & " - Account name: " & theItem's account as text
end try
end repeat
… and then even retrieve the passwords for the respective entry:
set keychain to current application's DTKeychain's sharedInstance()
set query to current application's DTKeychainGenericPassword's keychainItemQueryForService:("Service name") account:("Account name")
set {itemList, errorRes} to my (keychain's keychainItemsMatchingQuery:query |error|:(reference))
if itemList's |count|() > 0 then
set pass to itemList's firstObject()
if my (keychain's retrieveSecuredDataForKeychainItem:pass |error|:(missing value)) then
set thePassword to pass's |password| as text
end if
end if
You can’t do more with other languages, because not every process (or app) has access to every password in the keychain, and that’s a good thing.
@furbies:
Which user name and password do you want to retrieve from the keychain? One you have stored yourself with your applet? - That works (see the Sample). Or the system user name and password? - That would be bad if that were possible.
I’m needing an admin user & password because my little Applet needs to be able to de/activate the network interfaces as part of it’s little one trick usefulness.
So at the moment, I’m relying on the end user creating a password item in the login keychain, and in it, they store a admin user & password and then when they run my little Applet it requests access to the password item, and the user needs to give it elsewise the Applet can’t do it’s trick. This way my Applet doesn’t need to really know the user/pass in that the Applet doesn’t need to save the user/pass outside the keychain, and only uses it to do it’s trick, and the Applet doesn’t itself access the internet so it’s not “phoning home” any info…