@@ -52,6 +52,38 @@ extension OktaOidcStateManager: StateManagerProtocol {
5252
5353}
5454
55+ // MARK: - DeviceSecretKeychain
56+
57+ class DeviceSecretKeychain {
58+ var service : String
59+ var accessGroup : String
60+
61+ init ( service: String , accessGroup: String ) {
62+ self . service = service
63+ self . accessGroup = accessGroup
64+ }
65+
66+ func save( _ tokens: [ String : String ] ) {
67+ let query : [ String : Any ] = [
68+ ( kSecClass as String ) : kSecClassGenericPassword,
69+ ( kSecAttrService as String ) : service,
70+ ( kSecAttrAccessGroup as String ) : self . accessGroup]
71+ SecItemDelete ( query as CFDictionary )
72+
73+ for (kind, value) in tokens {
74+ let attributes : [ String : Any ] = [
75+ ( kSecClass as String ) : kSecClassGenericPassword,
76+ ( kSecAttrService as String ) : service,
77+ ( kSecAttrAccessGroup as String ) : self . accessGroup,
78+ ( kSecAttrAccount as String ) : " Okta- \( kind) " ,
79+ ( kSecValueData as String ) : value. data ( using: . utf8) !
80+ ]
81+
82+ SecItemAdd ( attributes as CFDictionary , nil )
83+ }
84+ }
85+ }
86+
5587// MARK: - OktaSdkBridge
5688
5789@objc ( OktaSdkBridge)
@@ -70,10 +102,11 @@ class OktaSdkBridge: RCTEventEmitter {
70102 }
71103
72104 var oktaOidc : OktaOidcProtocol ?
73-
105+
74106 override var methodQueue : DispatchQueue { . main }
75107
76108 private var requestTimeout : Int ?
109+ private var deviceSecretKeychain : DeviceSecretKeychain ?
77110
78111 func presentedViewController( ) -> UIViewController ? {
79112 RCTPresentedViewController ( )
@@ -85,6 +118,8 @@ class OktaSdkBridge: RCTEventEmitter {
85118 endSessionRedirectUri: String ,
86119 discoveryUri: String ,
87120 scopes: String ,
121+ keychainService: String ,
122+ keychainAccessGroup: String ,
88123 userAgentTemplate: String ,
89124 requestTimeout: Int ,
90125 promiseResolver: RCTPromiseResolveBlock ,
@@ -105,6 +140,7 @@ class OktaSdkBridge: RCTEventEmitter {
105140
106141 oktaOidc = try OktaOidc ( configuration: config)
107142 self . requestTimeout = requestTimeout
143+ self . deviceSecretKeychain = DeviceSecretKeychain ( service: keychainService, accessGroup: keychainAccessGroup)
108144
109145 promiseResolver ( true )
110146 } catch let error {
@@ -311,6 +347,15 @@ class OktaSdkBridge: RCTEventEmitter {
311347 }
312348
313349 currStateManager. writeToSecureStorage ( )
350+
351+ // Only use the DeviceSecretKeychain if the response includes a "device_secret" field
352+ if let deviceSecret = currStateManager. authState. lastTokenResponse!. additionalParameters![ " device_secret " ] as? String {
353+ self . deviceSecretKeychain!. save ( [
354+ " id_token " : currStateManager. idToken!,
355+ " device_secret " : deviceSecret
356+ ] )
357+ }
358+
314359 let dic = [
315360 OktaSdkConstant . RESOLVE_TYPE_KEY: OktaSdkConstant . AUTHORIZED,
316361 OktaSdkConstant . ACCESS_TOKEN_KEY: stateManager? . accessToken
0 commit comments