How to securely store the license key based purchases?

3 weeks ago 17
ARTICLE AD BOX

I am trying to implement license key logic in my app where users can enter the license key they bought from stripe or any payment provider and than, the entered license key would need to first verified. Now, currently I am using KeyChain to store the license key and checking everytime .hasPremiumAccess etc. however, there would be a keychain access prompt that would open first time the user tries to install the app / open it.

enter image description here

This seems to be very scary for anyone trying to use the app for the first time, and I want to completely remove this keychain logic and implement another robust method that doesn't require any permissions from user. Any advice would be appreciated :)

This is my entire code for keychain save and access :-

import Foundation import Security enum KeychainHelper { static let service = "app.mysomething.license" static let account = "my_license_token" static func save(_ data: Data) throws { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: account, kSecValueData as String: data, kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlock ] // Remove existing item (important) SecItemDelete(query as CFDictionary) let status = SecItemAdd(query as CFDictionary, nil) guard status == errSecSuccess else { throw NSError(domain: "Keychain", code: Int(status)) } } static func load() -> Data? { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: account, kSecReturnData as String: true, kSecMatchLimit as String: kSecMatchLimitOne ] var result: AnyObject? let status = SecItemCopyMatching(query as CFDictionary, &result) guard status == errSecSuccess else { return nil } return result as? Data } static func delete() { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: account ] SecItemDelete(query as CFDictionary) } }

The prompt shows up when the license key was store previously by the app and I reinstalled the app, for the first time load, it ask for that permission

Read Entire Article