kishikawakatsumi / KeychainAccess

Simple Swift wrapper for Keychain that works on iOS, watchOS, tvOS and macOS.
MIT License
7.95k stars 788 forks source link

Keychain and OnlyThisDevice #200

Closed itsjaychang closed 8 years ago

itsjaychang commented 8 years ago

Hi,

I'm new to Swift and I am trying to store the Keychains locally only and not across device. I tried setting .synchronizable(false), but I still get a "AfterFirstUnlock" which says that the Keychain migrates to new device. Also, keychain.accessibility(.AlwaysThisDeviceOnly) doesn't seem to work, still get "AfterFirstUnlock" when print(keychain.accessibility). Is there a way to set the Keychain to be only this device and not sync with icloud.

Sorry if this is a dumb question. Thanks

kishikawakatsumi commented 8 years ago

@jaychangs You would not like to migrate any keychain items to the new devices, right?

You should use WhenPasscodeSetThisDeviceOnly, WhenUnlockedThisDeviceOnly or AfterFirstUnlockThisDeviceOnly for Accessibility settings. Like the following:

let keychain = Keychain()
    .accessibility(.AfterFirstUnlockThisDeviceOnly)
keychain[userrname] = password
itsjaychang commented 8 years ago

@kishikawakatsumi Thanks for your response. I tried setting to

let keychain = Keychain()
keychain.accessibility(.WhenUnlockedThisDeviceOnly)

keychain["keychain"] = "message"

let x = keychain["keychain"]
print(keychain.accessibility)
print(x)

However when I check the attribute at the end, the print statements results are

AfterFirstUnlock
Optional("message")

It seems the attribute remains as AfterFirstUnlock. Is there something I am missing? Or is checking the attribute this way an incorrect way of looking at it.

kishikawakatsumi commented 8 years ago

@jaychangs KeychainAccess adopts method chain with fluent interface pattern.

http://martinfowler.com/bliki/FluentInterface.html

So you must chain or assign return value of the setting methods. Like following:

let keychain = Keychain(service: "com.example.github-token")
    .label("github.com (kishikawakatsumi)")
    .synchronizable(true)
    .accessibility(.AfterFirstUnlock)

Because any instances of Keychain are immutable. Any setting methods just return a copy.

public func accessibility(accessibility: Accessibility) -> Keychain {
    var options = self.options
    options.accessibility = accessibility
    return Keychain(options)
}

So you must use like following:

let keychain = Keychain()
    .accessibility(.WhenUnlockedThisDeviceOnly)

or like this:

let keychain = Keychain()
let deviceOnlyKeychain = keychain.accessibility(.WhenUnlockedThisDeviceOnly)
itsjaychang commented 8 years ago

@kishikawakatsumi Wow thanks, I learned something new.

Thanks for the quick replies and have a good day :>