{"id":5809,"library":"pyobjc-framework-localauthentication","title":"PyObjC LocalAuthentication Framework","description":"Wrappers for the framework LocalAuthentication on macOS. This library is part of the larger PyObjC project, a bridge between Python and Objective-C. It allows Python applications to leverage macOS's biometric authentication (Face ID, Touch ID) and passcode features for secure user authentication. Currently at version 12.1, it maintains an active release cadence, typically aligning with macOS SDK updates and Python version support.","status":"active","version":"12.1","language":"en","source_language":"en","source_url":"https://github.com/ronaldoussoren/pyobjc","tags":["macos","apple","authentication","biometrics","touchid","faceid","security","pyobjc","objective-c"],"install":[{"cmd":"pip install pyobjc-framework-localauthentication","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Core component of the PyObjC bridge, required for all framework wrappers.","package":"pyobjc-core","optional":false},{"reason":"Provides access to fundamental Cocoa classes.","package":"pyobjc-framework-cocoa","optional":false},{"reason":"Potentially used for underlying security operations by LocalAuthentication.","package":"pyobjc-framework-security","optional":false}],"imports":[{"note":"The primary class for evaluating authentication policies.","symbol":"LAContext","correct":"from LocalAuthentication import LAContext"},{"note":"Constants defining authentication policies (e.g., deviceOwnerAuthentication).","symbol":"LAPolicy","correct":"from LocalAuthentication import LAPolicy"},{"note":"Error codes for local authentication failures.","symbol":"LAError","correct":"from LocalAuthentication import LAError"}],"quickstart":{"code":"import objc\nfrom LocalAuthentication import LAContext, LAPolicy\n\ndef authenticate_user(reason=\"Authenticate to access sensitive data.\"):\n    context = LAContext.alloc().init()\n    error = objc.nil\n    can_evaluate = context.canEvaluatePolicy_error_(LAPolicy.deviceOwnerAuthenticationWithBiometrics, objc.byref(error))\n\n    if not can_evaluate:\n        if error is not objc.nil:\n            print(f\"Biometric authentication not available: {error.localizedDescription()}\")\n        else:\n            print(\"Biometric authentication not available.\")\n        # Fallback to device passcode if biometrics not available\n        can_evaluate = context.canEvaluatePolicy_error_(LAPolicy.deviceOwnerAuthentication, objc.byref(error))\n        if not can_evaluate:\n            if error is not objc.nil:\n                print(f\"Device passcode authentication not available: {error.localizedDescription()}\")\n            else:\n                print(\"Device passcode authentication not available.\")\n            return False\n\n    def reply_handler(success, err):\n        if success:\n            print(\"Authentication successful!\")\n        elif err is not objc.nil:\n            print(f\"Authentication failed: {err.localizedDescription()}\")\n        else:\n            print(\"Authentication failed (unknown error).\")\n\n    context.evaluatePolicy_localizedReason_reply_(LAPolicy.deviceOwnerAuthentication, reason, reply_handler)\n\n# Example usage:\n# Note: This will block the Python interpreter until authentication completes or fails.\n# In a real GUI app, this would typically be run on a background thread or using a runloop.\nauthenticate_user()\n\n# To run PyObjC event loop in a console application (optional, for persistent UI/callbacks):\n# from PyObjCTools import AppHelper\n# AppHelper.runEventLoop() # This should be called if you need to keep a UI or callbacks alive.","lang":"python","description":"This quickstart demonstrates how to use `LAContext` to evaluate an authentication policy, typically for biometric authentication (Face ID/Touch ID) or device passcode. It first checks if the policy can be evaluated and then calls `evaluatePolicy_localizedReason_reply_` with a callback function to handle the authentication result. Remember that `pyobjc-framework-localauthentication` is a macOS-only library and requires user interaction via a system prompt."},"warnings":[{"fix":"Ensure your Python environment is compatible with the PyObjC version you are installing. For `pyobjc-framework-localauthentication` 12.x, Python 3.10 or later is required. Always check `requires_python` on PyPI or the PyObjC changelog for specific version requirements.","message":"PyObjC frequently drops support for older Python versions. PyObjC 12.0 dropped support for Python 3.9, and PyObjC 11.0 dropped Python 3.8.","severity":"breaking","affected_versions":"11.0 and later"},{"fix":"Review code that interacts with object initialization, especially custom subclasses or factory methods, to ensure correct reference handling. While explicit memory management is rarely needed in Python, understanding the underlying Objective-C semantics is crucial for correct behavior.","message":"PyObjC 11.1 changed how Objective-C 'init' family methods are modeled, now correctly reflecting that they 'steal' a reference to `self` and return a new one, as per clang's Automatic Reference Counting (ARC) documentation.","severity":"breaking","affected_versions":"11.1 and later"},{"fix":"Always check for `None` before calling methods on PyObjC-wrapped objects that might originate from Objective-C `nil` values. E.g., `if my_obj is not None: my_obj.doSomething_()`.","message":"Unlike Objective-C, where sending a message to `nil` (equivalent to Python `None`) is a no-op, attempting to call a method on a Python `None` object (which PyObjC translates from `nil`) will raise an `AttributeError`.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Only use `pyobjc-framework-localauthentication` in macOS environments. For cross-platform authentication, consider alternative libraries.","message":"PyObjC is a macOS-specific library and will not install or run on other operating systems. The frameworks it wraps (like LocalAuthentication) are Apple-proprietary.","severity":"gotcha","affected_versions":"All versions"},{"fix":"When subclassing Objective-C classes in Python and overriding `__new__`, be extremely cautious with `__init__`. It's generally safer to perform all initialization logic within `__new__` or the appropriate Objective-C `init` equivalent. Refer to PyObjC documentation on subclassing for the most up-to-date guidance.","message":"PyObjC 10.3 introduced breaking changes around the interaction of `__init__` and `__new__` for Python subclasses of Objective-C objects. While 10.3.1 partially re-introduced `__init__` support when a user implements `__new__`, code relying on PyObjC's provided `__new__` still cannot use `__init__`. This can lead to `__init__` not being called or unexpected behavior.","severity":"gotcha","affected_versions":"10.3 and later (partially mitigated in 10.3.1)"}],"env_vars":null,"last_verified":"2026-04-14T00:00:00.000Z","next_check":"2026-07-13T00:00:00.000Z"}