Skip to content

Commit 1ef76e5

Browse files
committed
feat: Store device secret in keychain
1 parent b1e23ac commit 1ef76e5

7 files changed

Lines changed: 279 additions & 228 deletions

File tree

index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ export const createConfig = async({
6161
endSessionRedirectUri,
6262
discoveryUri,
6363
scopes,
64+
keychainService = 'Okta',
65+
keychainAccessGroup = 'com.okta.mobile-sdk.shared',
6466
requireHardwareBackedKeyStore,
6567
androidChromeTabColor,
6668
httpConnectionTimeout,
@@ -110,6 +112,8 @@ export const createConfig = async({
110112
endSessionRedirectUri,
111113
discoveryUri,
112114
scopes,
115+
keychainService,
116+
keychainAccessGroup,
113117
userAgentTemplate,
114118
httpConnectionTimeout,
115119
);

ios/OktaSdkBridge/OktaSdkBridge.swift

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

ios/OktaSdkBridge/ReactNativeOktaSdkBridge.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ @interface RCT_EXTERN_MODULE(OktaSdkBridge, RCTEventEmitter)
2121
endSessionRedirectUri:(NSString *)endSessionRedirectUri
2222
discoveryUri:(NSString *)discoveryUri
2323
scopes:(NSString *)scopes
24+
keychainService:(NSString *)keychainService
25+
keychainAccessGroup:(NSString *)keychainAccessGroup
2426
userAgentTemplate:(NSString *)userAgentTemplate
2527
requestTimeout:(NSInteger)requestTimeout
2628
promiseResolver:(RCTPromiseResolveBlock *)promiseResolver

0 commit comments

Comments
 (0)