ionic-team / capacitor-plugins

Official plugins for Capacitor ⚡️
523 stars 586 forks source link

MDM Managed User Defaults #557

Open danleedham opened 3 years ago

danleedham commented 3 years ago

Feature Request

Plugin

Storage

Description

In iOS 7 and later, a Mobile Device Management (MDM) server can use configuration and feedback dictionaries to communicate with and configure third-party managed apps.

With managed app configuration, MDM uses the native iOS management framework to configure apps during or after deployment. This framework enables developers to identify the configuration settings that should be implemented when their app is installed as a managed app. Employees can start using apps that have been configured this way right away, without requiring custom setup. IT gets the assurance that corporate data within apps is handled securely, with no need for proprietary SDKs or app wrapping. There are capabilities available to app developers that can be enabled using managed app configuration such as app configuration, prevent app backup, disable screen capture, and remotely wipe app.

Enterprise App developers can pass configuration strings to the app via a UserDefaults dictionary called com.apple.configuration.managed.

A simple addition to the Capacitor Storage plugin would allow developers to access the Strings contained within this UserDefaults Dictionary.

Platform(s)

iOS

Preferred Solution

A function (ie getManaged(key)) that allows developers to extract Strings from the Configuration Managed Dictionary for use in Capacitor.

Whilst I've managed to build the ability to extract the in a standalone SwiftUI App, my Swift ability is not where it should be. One extracts the dictionary with: UserDefaults.standard.dictionary(forKey: "com.apple.configuration.managed"), at which point you can extract the [key: value] as you'd expect.

In Storage.swift

public func getManaged(by key: String) -> String? {
       return String(describing: defaults.dictionary(forKey: "com.apple.configuration.managed")?[key] ?? "")
    }

In StoragePlugin.swift:

@objc func getManaged(_ call: CAPPluginCall) {
        guard let key = call.getString("key") else {
            call.reject("Must provide a key")
            return
        }

        let value = storage.getManaged(by: key)

        call.resolve([
            "value": value as String
        ])
    }

Alternatives

Implementation by adding a ConfigureOptions toggle, so that when set to 'managed', any key that is returned is actually the key from com.apple.configuration.managed. I have no idea how to efficiently implement this!

A standalone Plugin.

We could also build in functionality for setting the 'return' UserDefault which is called com.apple.feedback.managed for giving feedback back to the MDM.

Apple provide a NSUserDefaultsDidChangeNotification which could be observed for changes.

Additional Context

The best place for docs on this topic is: [https://www.appconfig.org/ios/]

From the Apple MDM Protocol Reference:

In iOS 7 and later, an MDM server can use configuration and feedback dictionaries to communicate with and configure third-party managed apps.

The configuration dictionary provides one-way communication from the MDM server to an app. An app can access its (read-only) configuration dictionary by reading the key com.apple.configuration.managed using the NSUserDefaults class. A managed app can respond to new configurations that arrive while the app is running by observing the NSUserDefaultsDidChangeNotification notification.

A managed app can also store feedback information that can be queried over MDM. An app can store new values for this feedback dictionary by setting the com.apple.feedback.managed key using the NSUserDefaults class. This dictionary can be read or deleted over MDM. An app can respond to the deletion of the feedback dictionary by observing the NSUserDefaultsDidChangeNotification notification.

Other info: https://developer.apple.com/library/archive/samplecode/sc2279/Introduction/Intro.html

From https://developer.apple.com/documentation/foundation/userdefaults Using Defaults in Managed Environments If your app supports managed environments, you can use UserDefaults to determine which preferences are managed by an administrator for the benefit of the user. In a managed environment, such as a computer lab or classroom, an administrator or teacher can configure the systems by establishing a set of default preferences for users. If a preference is managed in this manner (as determined by the methods described in Accessing Managed Environment Keys), your app should prevent users from editing that preference by disabling or hiding controls.

danleedham commented 3 years ago

https://github.com/danleedham/capacitor-plugins/commit/e0893c66151ff00a03d8a4137cbe70dbe3ec7ddc

robingenz commented 2 years ago

Hi @danleedham, I just discovered your issue by accident. I have created such a plugin last year but unfortunately didn't have the chance to test the iOS implementation. If you want you can try it out and give me feedback: https://github.com/robingenz/capacitor-managed-configurations

petarov commented 1 year ago

Managed com.apple.configuration.managed configurations are pretty common, especially in enterprise apps. It'd be great if the Preferences plugin offers this functionality.

@robingenz I'll take a look at your plugin. Thanks for mentioning!