square/Valet

Contexts being retained?

perlguy99 opened this issue · 3 comments

When I'm running several unit tests for my app, if I have a shared SinglePromptSecureEnclaveValet that I use from a "singleton helper", I get several errors like the following...

2020-07-27 10:10:08.967933-0500 Foo App[69001:6412884] [LAClient] Error Domain=com.apple.LocalAuthentication Code=-10 "Invalidated due to exceeded number of allocated contexts." UserInfo={NSLocalizedDescription=Invalidated due to exceeded number of allocated contexts.}

But if I use a SecureEnclaveValet instead, the issue does not appear.

Are contexts being created and not disposed of?

Here is the first part of my singleton class:

class ValetUtil {
    static var shared: ValetUtil = ValetUtil()
   var secureEnclave_ERROR: SinglePromptSecureEnclaveValet
    var secureEnclave: SecureEnclaveValet
    var keychain: Valet
   
    private init() {
        secureEnclave_ERROR = SinglePromptSecureEnclaveValet.valet(with: Identifier(nonEmpty: Constants.General.valet_id.rawValue)!, accessControl: .userPresence)
        secureEnclave       = SecureEnclaveValet.valet(with: Identifier(nonEmpty: Constants.General.valet_id.rawValue)!, accessControl: .userPresence)
        keychain            = Valet.valet(with: Identifier(nonEmpty: Constants.General.valet_id.rawValue)!, accessibility: .whenUnlocked)
    }
dfed commented

Thank you for the report! This is interesting 🤔. I have a bunch of questions:

  1. What operating system (platform and version) are you seeing this error on?
  2. What unexpected behavior (if any) are you seeing beyond the console log?
  3. How many SinglePromptSecureEnclaveValet instances do you have in your application?
  4. Do you ever call requirePromptOnNextAccess()?
  5. Do you use LAContext objects anywhere else in your application?
  6. Does this error occur at allocation time, at secret retrieval time, or some other time?

Are contexts being created and not disposed of?

We only explicitly retain a single LAContext per SinglePromptSecureEnclaveValet instance. We do put this object into dictionaries that we pass to the keychain, but those dictionaries are transient and only reference the LAContext object (reference rather than copy).

You nailed it! I found another class in our code that was creating LAContext objects and not getting rid of them when it was finished.

Sorry to have opened this without finding that first.

dfed commented

All good! Thanks for following up. Closing out this issue 🙂