@doko/react-native-yubikit 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/README.md +126 -0
- package/RNYubikit.podspec +22 -0
- package/android/build.gradle +63 -0
- package/android/src/main/AndroidManifest.xml +9 -0
- package/android/src/main/java/com/yubikit/YubiKitManagerHolder.kt +330 -0
- package/android/src/main/java/com/yubikit/YubikitCoreModule.kt +142 -0
- package/android/src/main/java/com/yubikit/YubikitFidoModule.kt +418 -0
- package/android/src/main/java/com/yubikit/YubikitManagementModule.kt +132 -0
- package/android/src/main/java/com/yubikit/YubikitOathModule.kt +224 -0
- package/android/src/main/java/com/yubikit/YubikitOpenPgpModule.kt +317 -0
- package/android/src/main/java/com/yubikit/YubikitPackage.kt +44 -0
- package/android/src/main/java/com/yubikit/YubikitPivModule.kt +310 -0
- package/android/src/main/java/com/yubikit/YubikitSupportModule.kt +108 -0
- package/android/src/main/java/com/yubikit/YubikitYubiOtpModule.kt +248 -0
- package/android/src/main/java/com/yubikit/utils/YubikitUtils.kt +321 -0
- package/ios/YubikitCore.h +5 -0
- package/ios/YubikitCore.mm +101 -0
- package/ios/YubikitDeviceInfoHelper.h +13 -0
- package/ios/YubikitDeviceInfoHelper.mm +110 -0
- package/ios/YubikitFido.h +5 -0
- package/ios/YubikitFido.mm +373 -0
- package/ios/YubikitManagement.h +5 -0
- package/ios/YubikitManagement.mm +153 -0
- package/ios/YubikitManager.h +27 -0
- package/ios/YubikitManager.m +169 -0
- package/ios/YubikitOath.h +5 -0
- package/ios/YubikitOath.mm +583 -0
- package/ios/YubikitOpenPgp.h +5 -0
- package/ios/YubikitOpenPgp.mm +210 -0
- package/ios/YubikitPiv.h +5 -0
- package/ios/YubikitPiv.mm +813 -0
- package/ios/YubikitSupport.h +5 -0
- package/ios/YubikitSupport.mm +58 -0
- package/ios/YubikitYubiOtp.h +5 -0
- package/ios/YubikitYubiOtp.mm +120 -0
- package/lib/module/core.js +34 -0
- package/lib/module/core.js.map +1 -0
- package/lib/module/fido.js +40 -0
- package/lib/module/fido.js.map +1 -0
- package/lib/module/hooks/index.js +5 -0
- package/lib/module/hooks/index.js.map +1 -0
- package/lib/module/hooks/use-yubikey.js +12 -0
- package/lib/module/hooks/use-yubikey.js.map +1 -0
- package/lib/module/hooks/yubikey-provider.js +85 -0
- package/lib/module/hooks/yubikey-provider.js.map +1 -0
- package/lib/module/index.js +12 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/management.js +17 -0
- package/lib/module/management.js.map +1 -0
- package/lib/module/oath.js +53 -0
- package/lib/module/oath.js.map +1 -0
- package/lib/module/openpgp.js +89 -0
- package/lib/module/openpgp.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/piv.js +71 -0
- package/lib/module/piv.js.map +1 -0
- package/lib/module/specs/NativeYubikitCore.js +10 -0
- package/lib/module/specs/NativeYubikitCore.js.map +1 -0
- package/lib/module/specs/NativeYubikitFido.js +5 -0
- package/lib/module/specs/NativeYubikitFido.js.map +1 -0
- package/lib/module/specs/NativeYubikitManagement.js +5 -0
- package/lib/module/specs/NativeYubikitManagement.js.map +1 -0
- package/lib/module/specs/NativeYubikitOath.js +5 -0
- package/lib/module/specs/NativeYubikitOath.js.map +1 -0
- package/lib/module/specs/NativeYubikitOpenPgp.js +5 -0
- package/lib/module/specs/NativeYubikitOpenPgp.js.map +1 -0
- package/lib/module/specs/NativeYubikitPiv.js +5 -0
- package/lib/module/specs/NativeYubikitPiv.js.map +1 -0
- package/lib/module/specs/NativeYubikitSupport.js +5 -0
- package/lib/module/specs/NativeYubikitSupport.js.map +1 -0
- package/lib/module/specs/NativeYubikitYubiOtp.js +5 -0
- package/lib/module/specs/NativeYubikitYubiOtp.js.map +1 -0
- package/lib/module/support.js +11 -0
- package/lib/module/support.js.map +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/yubiotp.js +32 -0
- package/lib/module/yubiotp.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/core.d.ts +14 -0
- package/lib/typescript/src/core.d.ts.map +1 -0
- package/lib/typescript/src/fido.d.ts +24 -0
- package/lib/typescript/src/fido.d.ts.map +1 -0
- package/lib/typescript/src/hooks/index.d.ts +3 -0
- package/lib/typescript/src/hooks/index.d.ts.map +1 -0
- package/lib/typescript/src/hooks/use-yubikey.d.ts +3 -0
- package/lib/typescript/src/hooks/use-yubikey.d.ts.map +1 -0
- package/lib/typescript/src/hooks/yubikey-provider.d.ts +23 -0
- package/lib/typescript/src/hooks/yubikey-provider.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +10 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/management.d.ts +8 -0
- package/lib/typescript/src/management.d.ts.map +1 -0
- package/lib/typescript/src/oath.d.ts +20 -0
- package/lib/typescript/src/oath.d.ts.map +1 -0
- package/lib/typescript/src/openpgp.d.ts +35 -0
- package/lib/typescript/src/openpgp.d.ts.map +1 -0
- package/lib/typescript/src/piv.d.ts +26 -0
- package/lib/typescript/src/piv.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeYubikitCore.d.ts +49 -0
- package/lib/typescript/src/specs/NativeYubikitCore.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeYubikitFido.d.ts +121 -0
- package/lib/typescript/src/specs/NativeYubikitFido.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeYubikitManagement.d.ts +53 -0
- package/lib/typescript/src/specs/NativeYubikitManagement.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeYubikitOath.d.ts +70 -0
- package/lib/typescript/src/specs/NativeYubikitOath.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeYubikitOpenPgp.d.ts +53 -0
- package/lib/typescript/src/specs/NativeYubikitOpenPgp.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeYubikitPiv.d.ts +47 -0
- package/lib/typescript/src/specs/NativeYubikitPiv.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeYubikitSupport.d.ts +49 -0
- package/lib/typescript/src/specs/NativeYubikitSupport.d.ts.map +1 -0
- package/lib/typescript/src/specs/NativeYubikitYubiOtp.d.ts +45 -0
- package/lib/typescript/src/specs/NativeYubikitYubiOtp.d.ts.map +1 -0
- package/lib/typescript/src/support.d.ts +6 -0
- package/lib/typescript/src/support.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +293 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/lib/typescript/src/yubiotp.d.ts +13 -0
- package/lib/typescript/src/yubiotp.d.ts.map +1 -0
- package/package.json +181 -0
- package/src/core.ts +58 -0
- package/src/fido.ts +112 -0
- package/src/hooks/index.tsx +2 -0
- package/src/hooks/use-yubikey.tsx +10 -0
- package/src/hooks/yubikey-provider.tsx +146 -0
- package/src/index.tsx +10 -0
- package/src/management.ts +44 -0
- package/src/oath.ts +134 -0
- package/src/openpgp.ts +220 -0
- package/src/piv.ts +193 -0
- package/src/specs/NativeYubikitCore.ts +68 -0
- package/src/specs/NativeYubikitFido.ts +149 -0
- package/src/specs/NativeYubikitManagement.ts +78 -0
- package/src/specs/NativeYubikitOath.ts +110 -0
- package/src/specs/NativeYubikitOpenPgp.ts +148 -0
- package/src/specs/NativeYubikitPiv.ts +108 -0
- package/src/specs/NativeYubikitSupport.ts +61 -0
- package/src/specs/NativeYubikitYubiOtp.ts +82 -0
- package/src/support.ts +18 -0
- package/src/types.ts +404 -0
- package/src/yubiotp.ts +96 -0
|
@@ -0,0 +1,583 @@
|
|
|
1
|
+
#import "YubikitOath.h"
|
|
2
|
+
#import "YubikitManager.h"
|
|
3
|
+
#import <YubiKit/YubiKit.h>
|
|
4
|
+
|
|
5
|
+
@implementation YubikitOath
|
|
6
|
+
|
|
7
|
+
#pragma mark - Helpers
|
|
8
|
+
|
|
9
|
+
- (id<YKFConnectionProtocol>)connectionForHandle:(NSString *)deviceHandle
|
|
10
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
11
|
+
id<YKFConnectionProtocol> connection = [[YubikitManager shared] connectionForHandle:deviceHandle];
|
|
12
|
+
if (connection == nil) {
|
|
13
|
+
reject(@"CONNECTION_ERROR", @"No device found for handle", nil);
|
|
14
|
+
}
|
|
15
|
+
return connection;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
- (YKFOATHCredentialType)oathTypeFromString:(NSString *)type {
|
|
19
|
+
if ([type isEqualToString:@"HOTP"]) return YKFOATHCredentialTypeHOTP;
|
|
20
|
+
return YKFOATHCredentialTypeTOTP;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
- (NSString *)stringFromOathType:(YKFOATHCredentialType)type {
|
|
24
|
+
return type == YKFOATHCredentialTypeHOTP ? @"HOTP" : @"TOTP";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
- (YKFOATHCredentialAlgorithm)algorithmFromString:(NSString *)algorithm {
|
|
28
|
+
if ([algorithm isEqualToString:@"SHA256"]) return YKFOATHCredentialAlgorithmSHA256;
|
|
29
|
+
if ([algorithm isEqualToString:@"SHA512"]) return YKFOATHCredentialAlgorithmSHA512;
|
|
30
|
+
return YKFOATHCredentialAlgorithmSHA1;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
- (NSString *)credentialIdFromCredential:(YKFOATHCredential *)credential {
|
|
34
|
+
NSDictionary *dict = @{
|
|
35
|
+
@"oathType": [self stringFromOathType:credential.type],
|
|
36
|
+
@"accountName": credential.accountName ?: @"",
|
|
37
|
+
@"issuer": credential.issuer ?: @"",
|
|
38
|
+
@"period": @(credential.period)
|
|
39
|
+
};
|
|
40
|
+
NSData *data = [NSJSONSerialization dataWithJSONObject:dict options:0 error:nil];
|
|
41
|
+
return [data base64EncodedStringWithOptions:0];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
- (nullable YKFOATHCredential *)findCredentialWithId:(NSString *)credentialId
|
|
45
|
+
inCredentialList:(NSArray<YKFOATHCredential *> *)credentials {
|
|
46
|
+
NSData *data = [[NSData alloc] initWithBase64EncodedString:credentialId options:0];
|
|
47
|
+
if (data == nil) return nil;
|
|
48
|
+
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
|
|
49
|
+
if (dict == nil) return nil;
|
|
50
|
+
|
|
51
|
+
NSString *type = dict[@"oathType"];
|
|
52
|
+
NSString *accountName = dict[@"accountName"];
|
|
53
|
+
NSString *issuer = dict[@"issuer"];
|
|
54
|
+
NSUInteger period = [dict[@"period"] unsignedIntegerValue];
|
|
55
|
+
YKFOATHCredentialType credentialType = [self oathTypeFromString:type];
|
|
56
|
+
|
|
57
|
+
for (YKFOATHCredential *credential in credentials) {
|
|
58
|
+
if (credential.type == credentialType &&
|
|
59
|
+
credential.period == period &&
|
|
60
|
+
[credential.accountName isEqualToString:accountName] &&
|
|
61
|
+
((credential.issuer == nil && [issuer length] == 0) || [credential.issuer isEqualToString:issuer])) {
|
|
62
|
+
return credential;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return nil;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
- (NSDictionary *)dictionaryFromCredential:(YKFOATHCredential *)credential {
|
|
69
|
+
return @{
|
|
70
|
+
@"id": [self credentialIdFromCredential:credential],
|
|
71
|
+
@"oathType": [self stringFromOathType:credential.type],
|
|
72
|
+
@"accountName": credential.accountName ?: @"",
|
|
73
|
+
@"issuer": credential.issuer ?: [NSNull null],
|
|
74
|
+
@"period": @(credential.period),
|
|
75
|
+
@"touchRequired": @(credential.requiresTouch)
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
- (NSDictionary *)dictionaryFromCode:(YKFOATHCode *)code {
|
|
80
|
+
NSTimeInterval validFrom = [code.validity.startDate timeIntervalSince1970] * 1000;
|
|
81
|
+
NSTimeInterval validUntil = [code.validity.endDate timeIntervalSince1970] * 1000;
|
|
82
|
+
return @{
|
|
83
|
+
@"value": code.otp ?: @"",
|
|
84
|
+
@"validFrom": @(validFrom),
|
|
85
|
+
@"validUntil": @(validUntil)
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
RCT_EXPORT_MODULE(YubikitOath)
|
|
90
|
+
|
|
91
|
+
- (void)getDeviceId:(NSString *)deviceHandle
|
|
92
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
93
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
94
|
+
id<YKFConnectionProtocol> connection = [self connectionForHandle:deviceHandle reject:reject];
|
|
95
|
+
if (!connection) return;
|
|
96
|
+
|
|
97
|
+
[connection oathSession:^(YKFOATHSession *_Nullable session, NSError *_Nullable error) {
|
|
98
|
+
if (error || session == nil) {
|
|
99
|
+
reject(@"OATH_ERROR", error ? error.localizedDescription : @"OATH session not available", error);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
resolve(session.deviceId);
|
|
103
|
+
}];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
- (void)reset:(NSString *)deviceHandle
|
|
107
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
108
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
109
|
+
id<YKFConnectionProtocol> connection = [self connectionForHandle:deviceHandle reject:reject];
|
|
110
|
+
if (!connection) return;
|
|
111
|
+
|
|
112
|
+
[connection oathSession:^(YKFOATHSession *_Nullable session, NSError *_Nullable error) {
|
|
113
|
+
if (error || session == nil) {
|
|
114
|
+
reject(@"OATH_ERROR", error ? error.localizedDescription : @"OATH session not available", error);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
[session resetWithCompletion:^(NSError *_Nullable error) {
|
|
118
|
+
if (error) {
|
|
119
|
+
reject(@"OATH_ERROR", error.localizedDescription, error);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
resolve(nil);
|
|
123
|
+
}];
|
|
124
|
+
}];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
- (void)isAccessKeySet:(NSString *)deviceHandle
|
|
128
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
129
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
130
|
+
id<YKFConnectionProtocol> connection = [self connectionForHandle:deviceHandle reject:reject];
|
|
131
|
+
if (!connection) return;
|
|
132
|
+
|
|
133
|
+
[connection oathSession:^(YKFOATHSession *_Nullable session, NSError *_Nullable error) {
|
|
134
|
+
if (error || session == nil) {
|
|
135
|
+
reject(@"OATH_ERROR", error ? error.localizedDescription : @"OATH session not available", error);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
// The iOS SDK does not expose "is a password configured" directly. The only signal
|
|
139
|
+
// available through public API is YKFOATHErrorCodeAuthenticationRequired from a
|
|
140
|
+
// command that needs auth, which proves a password IS set - but a *lack* of that
|
|
141
|
+
// error only proves the session isn't currently locked, not that no password was
|
|
142
|
+
// ever configured (it may have already been unlocked earlier in this connection's
|
|
143
|
+
// lifetime; see unlockWithPassword's docs). So this can under-report true here.
|
|
144
|
+
[session listCredentialsWithCompletion:^(NSArray<YKFOATHCredential *> *_Nullable credentials, NSError *_Nullable error) {
|
|
145
|
+
if (error && [error isKindOfClass:[YKFOATHError class]] && error.code == YKFOATHErrorCodeAuthenticationRequired) {
|
|
146
|
+
resolve(@YES);
|
|
147
|
+
} else if (error) {
|
|
148
|
+
reject(@"OATH_ERROR", error.localizedDescription, error);
|
|
149
|
+
} else {
|
|
150
|
+
resolve(@NO);
|
|
151
|
+
}
|
|
152
|
+
}];
|
|
153
|
+
}];
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
- (void)isLocked:(NSString *)deviceHandle
|
|
157
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
158
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
159
|
+
id<YKFConnectionProtocol> connection = [self connectionForHandle:deviceHandle reject:reject];
|
|
160
|
+
if (!connection) return;
|
|
161
|
+
|
|
162
|
+
[connection oathSession:^(YKFOATHSession *_Nullable session, NSError *_Nullable error) {
|
|
163
|
+
if (error || session == nil) {
|
|
164
|
+
reject(@"OATH_ERROR", error ? error.localizedDescription : @"OATH session not available", error);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
// Unlike isAccessKeySet, this only cares about the session's *current* auth state,
|
|
168
|
+
// which YKFOATHErrorCodeAuthenticationRequired answers precisely and reliably.
|
|
169
|
+
[session listCredentialsWithCompletion:^(NSArray<YKFOATHCredential *> *_Nullable credentials, NSError *_Nullable error) {
|
|
170
|
+
if (error && [error isKindOfClass:[YKFOATHError class]] && error.code == YKFOATHErrorCodeAuthenticationRequired) {
|
|
171
|
+
resolve(@YES);
|
|
172
|
+
} else if (error) {
|
|
173
|
+
reject(@"OATH_ERROR", error.localizedDescription, error);
|
|
174
|
+
} else {
|
|
175
|
+
resolve(@NO);
|
|
176
|
+
}
|
|
177
|
+
}];
|
|
178
|
+
}];
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
- (void)unlockWithPassword:(NSString *)deviceHandle
|
|
182
|
+
password:(NSString *)password
|
|
183
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
184
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
185
|
+
id<YKFConnectionProtocol> connection = [self connectionForHandle:deviceHandle reject:reject];
|
|
186
|
+
if (!connection) return;
|
|
187
|
+
|
|
188
|
+
[connection oathSession:^(YKFOATHSession *_Nullable session, NSError *_Nullable error) {
|
|
189
|
+
if (error || session == nil) {
|
|
190
|
+
reject(@"OATH_ERROR", error ? error.localizedDescription : @"OATH session not available", error);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
[session unlockWithPassword:password completion:^(NSError *_Nullable error) {
|
|
194
|
+
if (error) {
|
|
195
|
+
reject(@"OATH_ERROR", error.localizedDescription, error);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
resolve(@YES);
|
|
199
|
+
}];
|
|
200
|
+
}];
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
- (void)unlockWithAccessKey:(NSString *)deviceHandle
|
|
204
|
+
accessKey:(NSString *)accessKey
|
|
205
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
206
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
207
|
+
id<YKFConnectionProtocol> connection = [self connectionForHandle:deviceHandle reject:reject];
|
|
208
|
+
if (!connection) return;
|
|
209
|
+
|
|
210
|
+
[connection oathSession:^(YKFOATHSession *_Nullable session, NSError *_Nullable error) {
|
|
211
|
+
if (error || session == nil) {
|
|
212
|
+
reject(@"OATH_ERROR", error ? error.localizedDescription : @"OATH session not available", error);
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
NSData *keyData = [[NSData alloc] initWithBase64EncodedString:accessKey options:0];
|
|
216
|
+
if (keyData == nil) {
|
|
217
|
+
reject(@"OATH_ERROR", @"Invalid base64 access key", nil);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
[session unlockWithAccessKey:keyData completion:^(NSError *_Nullable error) {
|
|
221
|
+
if (error) {
|
|
222
|
+
reject(@"OATH_ERROR", error.localizedDescription, error);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
resolve(@YES);
|
|
226
|
+
}];
|
|
227
|
+
}];
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
- (void)setPassword:(NSString *)deviceHandle
|
|
231
|
+
password:(NSString *)password
|
|
232
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
233
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
234
|
+
id<YKFConnectionProtocol> connection = [self connectionForHandle:deviceHandle reject:reject];
|
|
235
|
+
if (!connection) return;
|
|
236
|
+
|
|
237
|
+
[connection oathSession:^(YKFOATHSession *_Nullable session, NSError *_Nullable error) {
|
|
238
|
+
if (error || session == nil) {
|
|
239
|
+
reject(@"OATH_ERROR", error ? error.localizedDescription : @"OATH session not available", error);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
[session setPassword:password completion:^(NSError *_Nullable error) {
|
|
243
|
+
if (error) {
|
|
244
|
+
reject(@"OATH_ERROR", error.localizedDescription, error);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
resolve(nil);
|
|
248
|
+
}];
|
|
249
|
+
}];
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
- (void)setAccessKey:(NSString *)deviceHandle
|
|
253
|
+
accessKey:(NSString *)accessKey
|
|
254
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
255
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
256
|
+
id<YKFConnectionProtocol> connection = [self connectionForHandle:deviceHandle reject:reject];
|
|
257
|
+
if (!connection) return;
|
|
258
|
+
|
|
259
|
+
[connection oathSession:^(YKFOATHSession *_Nullable session, NSError *_Nullable error) {
|
|
260
|
+
if (error || session == nil) {
|
|
261
|
+
reject(@"OATH_ERROR", error ? error.localizedDescription : @"OATH session not available", error);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
NSData *keyData = [[NSData alloc] initWithBase64EncodedString:accessKey options:0];
|
|
265
|
+
if (keyData == nil) {
|
|
266
|
+
reject(@"OATH_ERROR", @"Invalid base64 access key", nil);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
[session setAccessKey:keyData completion:^(NSError *_Nullable error) {
|
|
270
|
+
if (error) {
|
|
271
|
+
reject(@"OATH_ERROR", error.localizedDescription, error);
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
resolve(nil);
|
|
275
|
+
}];
|
|
276
|
+
}];
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
- (void)deleteAccessKey:(NSString *)deviceHandle
|
|
280
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
281
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
282
|
+
id<YKFConnectionProtocol> connection = [self connectionForHandle:deviceHandle reject:reject];
|
|
283
|
+
if (!connection) return;
|
|
284
|
+
|
|
285
|
+
[connection oathSession:^(YKFOATHSession *_Nullable session, NSError *_Nullable error) {
|
|
286
|
+
if (error || session == nil) {
|
|
287
|
+
reject(@"OATH_ERROR", error ? error.localizedDescription : @"OATH session not available", error);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
[session deleteAccessKeyWithCompletion:^(NSError *_Nullable error) {
|
|
291
|
+
if (error) {
|
|
292
|
+
reject(@"OATH_ERROR", error.localizedDescription, error);
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
resolve(nil);
|
|
296
|
+
}];
|
|
297
|
+
}];
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
- (void)getCredentials:(NSString *)deviceHandle
|
|
301
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
302
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
303
|
+
id<YKFConnectionProtocol> connection = [self connectionForHandle:deviceHandle reject:reject];
|
|
304
|
+
if (!connection) return;
|
|
305
|
+
|
|
306
|
+
[connection oathSession:^(YKFOATHSession *_Nullable session, NSError *_Nullable error) {
|
|
307
|
+
if (error || session == nil) {
|
|
308
|
+
reject(@"OATH_ERROR", error ? error.localizedDescription : @"OATH session not available", error);
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
[session listCredentialsWithCompletion:^(NSArray<YKFOATHCredential *> *_Nullable credentials, NSError *_Nullable error) {
|
|
312
|
+
if (error) {
|
|
313
|
+
reject(@"OATH_ERROR", error.localizedDescription, error);
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
NSMutableArray *result = [NSMutableArray arrayWithCapacity:credentials.count];
|
|
317
|
+
for (YKFOATHCredential *credential in credentials) {
|
|
318
|
+
[result addObject:[self dictionaryFromCredential:credential]];
|
|
319
|
+
}
|
|
320
|
+
resolve(@{@"credentials": result});
|
|
321
|
+
}];
|
|
322
|
+
}];
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
- (void)calculateCodes:(NSString *)deviceHandle
|
|
326
|
+
timestamp:(NSNumber *)timestamp
|
|
327
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
328
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
329
|
+
id<YKFConnectionProtocol> connection = [self connectionForHandle:deviceHandle reject:reject];
|
|
330
|
+
if (!connection) return;
|
|
331
|
+
|
|
332
|
+
[connection oathSession:^(YKFOATHSession *_Nullable session, NSError *_Nullable error) {
|
|
333
|
+
if (error || session == nil) {
|
|
334
|
+
reject(@"OATH_ERROR", error ? error.localizedDescription : @"OATH session not available", error);
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
YKFOATHSessionCalculateAllCompletionBlock completion = ^(NSArray<YKFOATHCredentialWithCode *> *_Nullable credentialsWithCodes, NSError *_Nullable error) {
|
|
339
|
+
if (error) {
|
|
340
|
+
reject(@"OATH_ERROR", error.localizedDescription, error);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
NSMutableArray *result = [NSMutableArray arrayWithCapacity:credentialsWithCodes.count];
|
|
344
|
+
for (YKFOATHCredentialWithCode *entry in credentialsWithCodes) {
|
|
345
|
+
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
|
|
346
|
+
dict[@"credential"] = [self dictionaryFromCredential:entry.credential];
|
|
347
|
+
if (entry.code) {
|
|
348
|
+
dict[@"code"] = [self dictionaryFromCode:entry.code];
|
|
349
|
+
}
|
|
350
|
+
[result addObject:dict];
|
|
351
|
+
}
|
|
352
|
+
resolve(@{@"codes": result});
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
if (timestamp) {
|
|
356
|
+
[session calculateAllWithTimestamp:[NSDate dateWithTimeIntervalSince1970:timestamp.doubleValue / 1000.0] completion:completion];
|
|
357
|
+
} else {
|
|
358
|
+
[session calculateAllWithCompletion:completion];
|
|
359
|
+
}
|
|
360
|
+
}];
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
- (void)calculateResponse:(NSString *)deviceHandle
|
|
364
|
+
credentialId:(NSString *)credentialId
|
|
365
|
+
challenge:(NSString *)challenge
|
|
366
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
367
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
368
|
+
id<YKFConnectionProtocol> connection = [self connectionForHandle:deviceHandle reject:reject];
|
|
369
|
+
if (!connection) return;
|
|
370
|
+
|
|
371
|
+
[connection oathSession:^(YKFOATHSession *_Nullable session, NSError *_Nullable error) {
|
|
372
|
+
if (error || session == nil) {
|
|
373
|
+
reject(@"OATH_ERROR", error ? error.localizedDescription : @"OATH session not available", error);
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
NSData *credentialIdData = [[NSData alloc] initWithBase64EncodedString:credentialId options:0];
|
|
378
|
+
NSData *challengeData = [[NSData alloc] initWithBase64EncodedString:challenge options:0];
|
|
379
|
+
if (challengeData == nil) {
|
|
380
|
+
reject(@"OATH_ERROR", @"Invalid base64 challenge", nil);
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
[session calculateResponseForCredentialID:credentialIdData ?: [NSData data]
|
|
385
|
+
challenge:challengeData
|
|
386
|
+
completion:^(NSData *_Nullable response, NSError *_Nullable error) {
|
|
387
|
+
if (error) {
|
|
388
|
+
reject(@"OATH_ERROR", error.localizedDescription, error);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
resolve([response base64EncodedStringWithOptions:0]);
|
|
392
|
+
}];
|
|
393
|
+
}];
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
- (void)calculateCode:(NSString *)deviceHandle
|
|
397
|
+
credentialId:(NSString *)credentialId
|
|
398
|
+
timestamp:(NSNumber *)timestamp
|
|
399
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
400
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
401
|
+
id<YKFConnectionProtocol> connection = [self connectionForHandle:deviceHandle reject:reject];
|
|
402
|
+
if (!connection) return;
|
|
403
|
+
|
|
404
|
+
[connection oathSession:^(YKFOATHSession *_Nullable session, NSError *_Nullable error) {
|
|
405
|
+
if (error || session == nil) {
|
|
406
|
+
reject(@"OATH_ERROR", error ? error.localizedDescription : @"OATH session not available", error);
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
[session listCredentialsWithCompletion:^(NSArray<YKFOATHCredential *> *_Nullable credentials, NSError *_Nullable error) {
|
|
411
|
+
if (error) {
|
|
412
|
+
reject(@"OATH_ERROR", error.localizedDescription, error);
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
YKFOATHCredential *credential = [self findCredentialWithId:credentialId inCredentialList:credentials];
|
|
416
|
+
if (credential == nil) {
|
|
417
|
+
reject(@"OATH_ERROR", @"Credential not found", nil);
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
YKFOATHSessionCalculateCompletionBlock completion = ^(YKFOATHCode *_Nullable code, NSError *_Nullable error) {
|
|
422
|
+
if (error) {
|
|
423
|
+
reject(@"OATH_ERROR", error.localizedDescription, error);
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
resolve([self dictionaryFromCode:code]);
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
if (timestamp) {
|
|
430
|
+
[session calculateCredential:credential timestamp:[NSDate dateWithTimeIntervalSince1970:timestamp.doubleValue / 1000.0] completion:completion];
|
|
431
|
+
} else {
|
|
432
|
+
[session calculateCredential:credential completion:completion];
|
|
433
|
+
}
|
|
434
|
+
}];
|
|
435
|
+
}];
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
- (void)putCredential:(NSString *)deviceHandle
|
|
439
|
+
credentialData:(JS::NativeYubikitOath::CredentialData &)credentialData
|
|
440
|
+
requireTouch:(BOOL)requireTouch
|
|
441
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
442
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
443
|
+
id<YKFConnectionProtocol> connection = [self connectionForHandle:deviceHandle reject:reject];
|
|
444
|
+
if (!connection) return;
|
|
445
|
+
|
|
446
|
+
NSData *secret = [[NSData alloc] initWithBase64EncodedString:credentialData.secret() options:0];
|
|
447
|
+
if (secret == nil) {
|
|
448
|
+
reject(@"OATH_ERROR", @"Invalid base64 secret", nil);
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
YKFOATHCredentialTemplate *credentialTemplate = [[YKFOATHCredentialTemplate alloc]
|
|
453
|
+
initWithType:[self oathTypeFromString:credentialData.oathType()]
|
|
454
|
+
algorithm:[self algorithmFromString:credentialData.hashAlgorithm()]
|
|
455
|
+
secret:secret
|
|
456
|
+
issuer:credentialData.issuer()
|
|
457
|
+
accountName:credentialData.accountName()
|
|
458
|
+
digits:(NSUInteger)credentialData.digits()
|
|
459
|
+
period:(NSUInteger)credentialData.period()
|
|
460
|
+
counter:(UInt32)credentialData.counter()];
|
|
461
|
+
|
|
462
|
+
if (credentialTemplate == nil) {
|
|
463
|
+
reject(@"OATH_ERROR", @"Invalid credential data", nil);
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
[connection oathSession:^(YKFOATHSession *_Nullable session, NSError *_Nullable error) {
|
|
468
|
+
if (error || session == nil) {
|
|
469
|
+
reject(@"OATH_ERROR", error ? error.localizedDescription : @"OATH session not available", error);
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
[session putCredentialTemplate:credentialTemplate requiresTouch:requireTouch completion:^(NSError *_Nullable error) {
|
|
473
|
+
if (error) {
|
|
474
|
+
reject(@"OATH_ERROR", error.localizedDescription, error);
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// Build a credential-like response from the template data.
|
|
479
|
+
NSDictionary *idDict = @{
|
|
480
|
+
@"oathType": credentialData.oathType(),
|
|
481
|
+
@"accountName": credentialData.accountName(),
|
|
482
|
+
@"issuer": credentialData.issuer() ?: @"",
|
|
483
|
+
@"period": @(credentialData.period())
|
|
484
|
+
};
|
|
485
|
+
NSData *idData = [NSJSONSerialization dataWithJSONObject:idDict options:0 error:nil];
|
|
486
|
+
NSString *credentialId = [idData base64EncodedStringWithOptions:0];
|
|
487
|
+
|
|
488
|
+
NSMutableDictionary *result = [NSMutableDictionary dictionary];
|
|
489
|
+
result[@"id"] = credentialId ?: @"";
|
|
490
|
+
result[@"oathType"] = credentialData.oathType();
|
|
491
|
+
result[@"accountName"] = credentialData.accountName();
|
|
492
|
+
result[@"issuer"] = credentialData.issuer() ?: [NSNull null];
|
|
493
|
+
result[@"period"] = @(credentialData.period());
|
|
494
|
+
result[@"touchRequired"] = @(requireTouch);
|
|
495
|
+
resolve(result);
|
|
496
|
+
}];
|
|
497
|
+
}];
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
- (void)deleteCredential:(NSString *)deviceHandle
|
|
501
|
+
credentialId:(NSString *)credentialId
|
|
502
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
503
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
504
|
+
id<YKFConnectionProtocol> connection = [self connectionForHandle:deviceHandle reject:reject];
|
|
505
|
+
if (!connection) return;
|
|
506
|
+
|
|
507
|
+
[connection oathSession:^(YKFOATHSession *_Nullable session, NSError *_Nullable error) {
|
|
508
|
+
if (error || session == nil) {
|
|
509
|
+
reject(@"OATH_ERROR", error ? error.localizedDescription : @"OATH session not available", error);
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
[session listCredentialsWithCompletion:^(NSArray<YKFOATHCredential *> *_Nullable credentials, NSError *_Nullable error) {
|
|
514
|
+
if (error) {
|
|
515
|
+
reject(@"OATH_ERROR", error.localizedDescription, error);
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
YKFOATHCredential *credential = [self findCredentialWithId:credentialId inCredentialList:credentials];
|
|
519
|
+
if (credential == nil) {
|
|
520
|
+
reject(@"OATH_ERROR", @"Credential not found", nil);
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
[session deleteCredential:credential completion:^(NSError *_Nullable error) {
|
|
525
|
+
if (error) {
|
|
526
|
+
reject(@"OATH_ERROR", error.localizedDescription, error);
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
resolve(nil);
|
|
530
|
+
}];
|
|
531
|
+
}];
|
|
532
|
+
}];
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
- (void)renameCredential:(NSString *)deviceHandle
|
|
536
|
+
credentialId:(NSString *)credentialId
|
|
537
|
+
newAccountName:(NSString *)newAccountName
|
|
538
|
+
newIssuer:(NSString *)newIssuer
|
|
539
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
540
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
541
|
+
id<YKFConnectionProtocol> connection = [self connectionForHandle:deviceHandle reject:reject];
|
|
542
|
+
if (!connection) return;
|
|
543
|
+
|
|
544
|
+
[connection oathSession:^(YKFOATHSession *_Nullable session, NSError *_Nullable error) {
|
|
545
|
+
if (error || session == nil) {
|
|
546
|
+
reject(@"OATH_ERROR", error ? error.localizedDescription : @"OATH session not available", error);
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
[session listCredentialsWithCompletion:^(NSArray<YKFOATHCredential *> *_Nullable credentials, NSError *_Nullable error) {
|
|
551
|
+
if (error) {
|
|
552
|
+
reject(@"OATH_ERROR", error.localizedDescription, error);
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
YKFOATHCredential *credential = [self findCredentialWithId:credentialId inCredentialList:credentials];
|
|
556
|
+
if (credential == nil) {
|
|
557
|
+
reject(@"OATH_ERROR", @"Credential not found", nil);
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
[session renameCredential:credential
|
|
562
|
+
newIssuer:newIssuer
|
|
563
|
+
newAccount:newAccountName
|
|
564
|
+
completion:^(NSError *_Nullable error) {
|
|
565
|
+
if (error) {
|
|
566
|
+
reject(@"OATH_ERROR", error.localizedDescription, error);
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
NSMutableDictionary *result = [NSMutableDictionary dictionaryWithDictionary:[self dictionaryFromCredential:credential]];
|
|
571
|
+
result[@"accountName"] = newAccountName;
|
|
572
|
+
result[@"issuer"] = newIssuer ?: [NSNull null];
|
|
573
|
+
resolve(result);
|
|
574
|
+
}];
|
|
575
|
+
}];
|
|
576
|
+
}];
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params {
|
|
580
|
+
return std::make_shared<facebook::react::NativeYubikitOathSpecJSI>(params);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
@end
|