Can't instantiate SFAuthorizationPluginView using Swift

Hi there,

I’m having issue using Apple’s API. I can’t initialize SFAuthorizationPluginView using Swift.

I’ve done numerous google searches, but haven’t found any examples/tutorials of anyone using Swift for SFAuthorizationPluginView / AuthorizationPluginCreate. I managed to get the AuthorizationPlugin and AuthorizationMechanism up, but simply creating the SFAuthorizationPluginView fails the failable initiator.

https://developer.apple.com/documentation/securityinterface/sfauthorizationpluginview

Here are some log messages I wrote:

error	16:08:33.689244-0800	kernel	Library Validation failed: Rejecting '/Library/Security/SecurityAgentPlugins/XXXAgent.bundle/Contents/MacOS/XXXAgent' (Team ID: 7X6364JT77, platform: no) for process 'SecurityAgentHel(2689)' (Team ID: N/A, platform: yes), reason: mapping process is a platform binary, but mapped file is not
error	16:08:33.689501-0800	SecurityAgentHelper-arm64	Error loading /Library/Security/SecurityAgentPlugins/XXXAgent.bundle/Contents/MacOS/XXXAgent (78):  dlopen(/Library/Security/SecurityAgentPlugins/XXXAgent.bundle/Contents/MacOS/XXXAgent, 0x0106): tried: '/Library/Security/SecurityAgentPlugins/XXXAgent.bundle/Contents/MacOS/XXXAgent' (code signature in <BFF0D7BA-5CF8-3F2F-A604-DCC235499234> '/Library/Security/SecurityAgentPlugins/XXXAgent.bundle/Contents/MacOS/XXXAgent' not valid for use in process: mapping process is a platform binary, but mapped file is not), '/System/Volumes/Preboot/Cryptexes/OS/Library/Security/SecurityAgentPlugins/XXXAgent.bundle/Contents/MacOS/XXXAgent' (no such file), '/Library/Security/SecurityAgentPlugins/XXXAgent.bundle/Contents/MacOS/XXXAgent' (code signature in <BFF0D7BA-5CF8-3F2F-A604-DCC235499234> '/Library/Security/SecurityAgentPlugins/XXXAgent.bundle/Contents/MacOS/XXXAgent' not valid for use in process: mapping process is a platform binary, but mapped file is not)
default	16:08:33.760679-0800	SecurityAgentHelper-arm64	callbacks: Optional(0x00000001001b1f88)
default	16:08:33.760710-0800	SecurityAgentHelper-arm64	andEngineRef: Optional(0x0000000156f384d0)
error	16:08:33.762404-0800	SecurityAgentHelper-arm64	Test API call result: OSStatus 0 i.e. No error.
error	16:08:33.763298-0800	SecurityAgentHelper-arm64	Failed to create Authorization Plugin Adapter
default	16:08:33.763524-0800	authd	engine 66: running mechanism XXXAgent:XXXAgentMechanism (1 of 1)

Here is the calling code with the error message:

class AuthorizationMechanismXXX : AuthorizationMechanism
{
    let mLogger = …
    
    let mAuthorizationPluginView : AuthorizationPluginViewAdapter?

    override init(inPlugin: UnsafeMutablePointer<AuthorizationPlugin>,
        inEngine: AuthorizationEngineRef,
        inMechanismId: AuthorizationMechanismId)
    {
…
        let pCallbacks : UnsafePointer<AuthorizationCallbacks> = inPlugin.pointee.EngineCallback()

        self.mAuthorizationPluginView = AuthorizationPluginViewAdapter(callbacks: pCallbacks, andEngineRef: inEngine)
 
        if (self.mAuthorizationPluginView == nil)
        {
            mLogger.error("Failed to create Authorization Plugin Adapter")
        }

        super.init(inPlugin: inPlugin, inEngine: inEngine, inMechanismId: inMechanismId)
    }

Here is the class:

class AuthorizationPluginViewAdapter : SFAuthorizationPluginView
{
    let mLogger = …
    let mLoginView = NSHostingView(rootView: LoginView())
    
    override init!(callbacks: UnsafePointer<AuthorizationCallbacks>!, andEngineRef engineRef: AuthorizationEngineRef!)
    {
        mLogger.notice("callbacks: \(callbacks.debugDescription, privacy: .public)")
        mLogger.notice("andEngineRef: \(engineRef.debugDescription, privacy: .public)")
        
        var sessionId: UnsafeMutablePointer<AuthorizationSessionId?>?
        let result = callbacks.pointee.GetSessionId(engineRef, sessionId)
        
        LogSecurityOSStatus(logger: mLogger, osStatus: result, message: "Test API call result")
        
        super.init(callbacks: callbacks, andEngineRef: engineRef)
        
        mLogger.notice("Never gets here")
    }
    
    override func buttonPressed(_ inButtonType: SFButtonType)
    {
        if (inButtonType == SFButtonTypeOK)
        {
            let osStatus = callbacks().pointee.SetResult(engineRef(), AuthorizationResult.allow)
            if (osStatus != errSecSuccess)
            {
                LogSecurityOSStatus(logger: mLogger, osStatus: osStatus, message: "Error setting authorization result")
            }
        }
        else if (inButtonType == SFButtonTypeCancel)
        {
            let osStatus = callbacks().pointee.SetResult(engineRef(), AuthorizationResult.deny)
            if osStatus != errSecSuccess
            {
                LogSecurityOSStatus(logger: mLogger, osStatus: osStatus, message: "Error setting authorization result")
            }
        }
        else
        {
            mLogger.error("Invalid buttonType.")
        }
    }

    override func view(for inType: SFViewType) -> NSView!
    {
        if (inType == SFViewTypeIdentityAndCredentials)
        {
            mLogger.debug("Identity and credentials")
        }
        else if (inType == SFViewTypeCredentials)
        {
            mLogger.debug("Credentials only")
        }
        else
        {
            mLogger.error("Invalid buttonType.")
        }
        return mLoginView
    }
}

Here is the view:

import SwiftUI

struct LoginView: View {
    var body: some View {
        Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
    }
}

#Preview {
    LoginView()
}

Replies

SFAuthorizationPluginView instances are intended to be hosted by authorisation plug-ins. You can’t use SwiftUI previews to test them.

You may be able to use SwiftUI within your view, via NSHostingView, but I strongly recommend that you stick with AppKit. Getting SFAuthorizationPluginView to work at all is hard. Adding SwiftUI into the mix is just going to make it harder.

[I] haven’t found any examples/tutorials of anyone using Swift for … AuthorizationPluginCreate.

It is possible to create an authorisation plug-in in Swift [1] but it’s really tricky. This is far too tricky to explain here; if you’re just starting out, I encourage you to start a DTS tech support incident so that I can get you on the right path.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Although not in 100% Swift. An authorisation plug-in requires that you export a function called AuthorizationPluginCreate with C calling conventions, and there’s not supported way to do that (see this thread on Swift Forums).