Is it problematic to use iCloud user IDs and zone IDs as keys in UserDefaults?

CloudKit documentation states that tokens for CKFetchDatabaseChangesOperation and CKFetchRecordZoneChangesOperation aren't compatible and should be segregated in app's cache.

I have written a class to help persist these tokens in UserDefaults (code below). The class constructs strings to be used as UserDefaults keys based on the following logic:

  • For zones, zoneID.ownerName + zoneID.zoneName, which results in something like _defaultOwner__Employees
  • For databases, "db" + database.databaseScope.rawValue, which results in something like db3 for shared database

While I'm quite happy how this works, I've realized that this exposes iCloud userIDs when you persist a zone from a shared database. How big of a security problem is this? Any suggestions what I could do differently?

Code: (also available as GitHub gist)

import CloudKit



final class ChangeTokenCache {



    // MARK: - Zone support



    /// Determines a unique UserDefaults key for storing zone change tokens

    /// like from CKFetchRecordZoneChangesOperation

    private static func userDefaultsKey(_ zoneID: CKRecordZone.ID) -> String {

        return "token_" + zoneID.ownerName + zoneID.zoneName

    }



    /// Persists a zone change token in standard UserDefaults

    static func setZoneToken(_ zoneID: CKRecordZone.ID, token: CKServerChangeToken?) {

        setToken(userDefaultsKey(zoneID), token: token)

    }



    /// Fetches a zone change token from standard UserDefaults

    static func getZoneToken(_ zoneID: CKRecordZone.ID) -> CKServerChangeToken? {

        return getToken(userDefaultsKey(zoneID))

    }



    // MARK: - Database support



    /// Determines a unique UserDefaults key for storing database change tokens

    /// like from CKFetchDatabaseChangesOperation

    private static func userDefaultsKey(_ database: CKDatabase) -> String {

        return "token_db\(database.databaseScope.rawValue)"

    }



    /// Persists a database change token in standard UserDefaults

    static func setDatabaseToken(_ database: CKDatabase, token: CKServerChangeToken?) {

        setToken(userDefaultsKey(database), token: token)

    }



    /// Fetches a database change token from standard UserDefaults

    static func getDatabaseToken(_ database: CKDatabase) -> CKServerChangeToken? {

        return getToken(userDefaultsKey(database))

    }



    // MARK: - Actual workers



    /// Private method that archives a token as data and persists that to UserDefaults

    private static func setToken(_ userDefaultsKey: String, token: CKServerChangeToken?) {

        if let token = token,

           let data = try? NSKeyedArchiver.archivedData(withRootObject: token, requiringSecureCoding: false) {

            UserDefaults.standard.set(data, forKey: userDefaultsKey)

        } else {

            UserDefaults.standard.removeObject(forKey: userDefaultsKey)

        }

    }



    /// Private method that gets data from UserDefaults and unarchives it as a token

    private static func getToken(_ userDefaultsKey: String) -> CKServerChangeToken? {

        guard let data = UserDefaults.standard.value(forKey: userDefaultsKey) as? Data else { return nil }

        var token: CKServerChangeToken?

        do {

            token = try NSKeyedUnarchiver.unarchivedObject(ofClass: CKServerChangeToken.self, from: data)

        } catch {

            token = nil

        }

        return token

    }

}