react-native-intune 0.1.0-alpha.1

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.
Files changed (110) hide show
  1. package/LICENSE +27 -0
  2. package/NOTICE +49 -0
  3. package/README.md +164 -0
  4. package/RNIntune.podspec +69 -0
  5. package/android/build.gradle +152 -0
  6. package/android/consumer-rules.pro +28 -0
  7. package/android/src/main/AndroidManifest.xml +2 -0
  8. package/android/src/main/java/com/reactnativeintune/RNIntuneAuth.kt +330 -0
  9. package/android/src/main/java/com/reactnativeintune/RNIntuneAuthCallback.kt +195 -0
  10. package/android/src/main/java/com/reactnativeintune/RNIntuneConfig.kt +63 -0
  11. package/android/src/main/java/com/reactnativeintune/RNIntuneEventQueue.kt +50 -0
  12. package/android/src/main/java/com/reactnativeintune/RNIntuneModule.kt +752 -0
  13. package/android/src/main/java/com/reactnativeintune/RNIntuneMsalConfig.kt +78 -0
  14. package/android/src/main/java/com/reactnativeintune/RNIntuneNotifications.kt +187 -0
  15. package/android/src/main/java/com/reactnativeintune/RNIntunePackage.kt +33 -0
  16. package/android/src/main/java/com/reactnativeintune/RNIntunePolicy.kt +108 -0
  17. package/android/src/main/java/com/reactnativeintune/RNIntuneReset.kt +85 -0
  18. package/android/src/main/java/com/reactnativeintune/RNIntuneResetJournal.kt +140 -0
  19. package/app.plugin.js +10 -0
  20. package/ios/RNIntune.h +20 -0
  21. package/ios/RNIntune.mm +467 -0
  22. package/ios/RNIntuneAuth.h +121 -0
  23. package/ios/RNIntuneAuth.m +390 -0
  24. package/ios/RNIntuneCore.h +150 -0
  25. package/ios/RNIntuneCore.m +535 -0
  26. package/ios/RNIntuneDelegates.h +70 -0
  27. package/ios/RNIntuneDelegates.m +268 -0
  28. package/ios/RNIntunePendingRequests.h +57 -0
  29. package/ios/RNIntunePendingRequests.m +230 -0
  30. package/ios/RNIntunePlistGuard.h +37 -0
  31. package/ios/RNIntunePlistGuard.m +147 -0
  32. package/ios/RNIntunePolicy.h +25 -0
  33. package/ios/RNIntunePolicy.m +112 -0
  34. package/ios/RNIntuneReset.h +34 -0
  35. package/ios/RNIntuneReset.m +93 -0
  36. package/ios/RNIntuneResetJournal.h +69 -0
  37. package/ios/RNIntuneResetJournal.m +106 -0
  38. package/lib/module/NativeIntune.js +20 -0
  39. package/lib/module/NativeIntune.js.map +1 -0
  40. package/lib/module/api/auth.js +66 -0
  41. package/lib/module/api/auth.js.map +1 -0
  42. package/lib/module/api/enrollment.js +104 -0
  43. package/lib/module/api/enrollment.js.map +1 -0
  44. package/lib/module/api/events.js +50 -0
  45. package/lib/module/api/events.js.map +1 -0
  46. package/lib/module/api/lifecycle.js +73 -0
  47. package/lib/module/api/lifecycle.js.map +1 -0
  48. package/lib/module/api/policy.js +23 -0
  49. package/lib/module/api/policy.js.map +1 -0
  50. package/lib/module/api/tokenProvider.js +80 -0
  51. package/lib/module/api/tokenProvider.js.map +1 -0
  52. package/lib/module/index.js +82 -0
  53. package/lib/module/index.js.map +1 -0
  54. package/lib/module/internal/decode.js +153 -0
  55. package/lib/module/internal/decode.js.map +1 -0
  56. package/lib/module/internal/emitter.js +15 -0
  57. package/lib/module/internal/emitter.js.map +1 -0
  58. package/lib/module/internal/errors.js +32 -0
  59. package/lib/module/internal/errors.js.map +1 -0
  60. package/lib/module/package.json +1 -0
  61. package/lib/module/types.js +143 -0
  62. package/lib/module/types.js.map +1 -0
  63. package/lib/typescript/package.json +1 -0
  64. package/lib/typescript/src/NativeIntune.d.ts +120 -0
  65. package/lib/typescript/src/NativeIntune.d.ts.map +1 -0
  66. package/lib/typescript/src/api/auth.d.ts +37 -0
  67. package/lib/typescript/src/api/auth.d.ts.map +1 -0
  68. package/lib/typescript/src/api/enrollment.d.ts +54 -0
  69. package/lib/typescript/src/api/enrollment.d.ts.map +1 -0
  70. package/lib/typescript/src/api/events.d.ts +24 -0
  71. package/lib/typescript/src/api/events.d.ts.map +1 -0
  72. package/lib/typescript/src/api/lifecycle.d.ts +33 -0
  73. package/lib/typescript/src/api/lifecycle.d.ts.map +1 -0
  74. package/lib/typescript/src/api/policy.d.ts +14 -0
  75. package/lib/typescript/src/api/policy.d.ts.map +1 -0
  76. package/lib/typescript/src/api/tokenProvider.d.ts +18 -0
  77. package/lib/typescript/src/api/tokenProvider.d.ts.map +1 -0
  78. package/lib/typescript/src/index.d.ts +67 -0
  79. package/lib/typescript/src/index.d.ts.map +1 -0
  80. package/lib/typescript/src/internal/decode.d.ts +48 -0
  81. package/lib/typescript/src/internal/decode.d.ts.map +1 -0
  82. package/lib/typescript/src/internal/emitter.d.ts +11 -0
  83. package/lib/typescript/src/internal/emitter.d.ts.map +1 -0
  84. package/lib/typescript/src/internal/errors.d.ts +22 -0
  85. package/lib/typescript/src/internal/errors.d.ts.map +1 -0
  86. package/lib/typescript/src/types.d.ts +317 -0
  87. package/lib/typescript/src/types.d.ts.map +1 -0
  88. package/package.json +204 -0
  89. package/plugin/transforms.js +153 -0
  90. package/plugin/withIntune.js +320 -0
  91. package/scripts/cli.mjs +72 -0
  92. package/scripts/doctor.mjs +232 -0
  93. package/scripts/fetch-sdks.mjs +456 -0
  94. package/scripts/lib/checks.mjs +720 -0
  95. package/scripts/lib/project.mjs +196 -0
  96. package/scripts/setup.mjs +233 -0
  97. package/sdk-lock.json +27 -0
  98. package/sdk-versions.json +70 -0
  99. package/src/NativeIntune.ts +130 -0
  100. package/src/api/auth.ts +73 -0
  101. package/src/api/enrollment.ts +112 -0
  102. package/src/api/events.ts +87 -0
  103. package/src/api/lifecycle.ts +75 -0
  104. package/src/api/policy.ts +22 -0
  105. package/src/api/tokenProvider.ts +80 -0
  106. package/src/index.ts +127 -0
  107. package/src/internal/decode.ts +191 -0
  108. package/src/internal/emitter.ts +14 -0
  109. package/src/internal/errors.ts +43 -0
  110. package/src/types.ts +381 -0
@@ -0,0 +1,390 @@
1
+ //
2
+ // Copyright (c) 2026 react-native-intune contributors. MIT.
3
+ //
4
+
5
+ #import "RNIntuneAuth.h"
6
+ #import "RNIntuneCore.h"
7
+
8
+ #import <MSAL/MSAL.h>
9
+
10
+ /// The scope a sign-in falls back to. See the note on `defaultScopes` in the header for
11
+ /// why this cannot be `openid profile offline_access`.
12
+ static NSString *const RNIntuneDefaultScope = @"https://graph.microsoft.com/User.Read";
13
+
14
+ @implementation RNIntuneAuth {
15
+ MSALPublicClientApplication *_client;
16
+ }
17
+
18
+ + (NSArray<NSString *> *)defaultScopes
19
+ {
20
+ return @[ RNIntuneDefaultScope ];
21
+ }
22
+
23
+ #pragma mark - Configuration
24
+
25
+ - (BOOL)configureWithClientId:(NSString *)clientId
26
+ authority:(NSString *)authority
27
+ redirectUri:(NSString *)redirectUri
28
+ keychainGroup:(NSString *)keychainGroup
29
+ error:(NSError **)error
30
+ {
31
+ NSURL *authorityUrl = [NSURL URLWithString:authority];
32
+ if (authorityUrl == nil) {
33
+ if (error != NULL) {
34
+ *error = [RNIntuneCore
35
+ errorWithCode:RNIntuneErrorNative
36
+ message:@"The authority is not a valid URL. Expected something like "
37
+ @"https://login.microsoftonline.com/<tenantId>."];
38
+ }
39
+ return NO;
40
+ }
41
+
42
+ NSError *authorityError = nil;
43
+ MSALAADAuthority *aadAuthority = [[MSALAADAuthority alloc] initWithURL:authorityUrl
44
+ error:&authorityError];
45
+ if (aadAuthority == nil) {
46
+ if (error != NULL) {
47
+ *error = [RNIntuneCore
48
+ errorWithCode:RNIntuneErrorNative
49
+ message:[NSString stringWithFormat:@"MSAL rejected the authority: %@",
50
+ authorityError
51
+ .localizedDescription
52
+ ?: @"unknown reason"]];
53
+ }
54
+ return NO;
55
+ }
56
+
57
+ MSALPublicClientApplicationConfig *config =
58
+ [[MSALPublicClientApplicationConfig alloc] initWithClientId:clientId
59
+ redirectUri:redirectUri
60
+ authority:aadAuthority];
61
+
62
+ // Only when the host plist asked for one. MSAL's own default is already
63
+ // `com.microsoft.adalcache`, which is what the Intune SDK looks in — writing that
64
+ // constant here by hand would just be a second place for it to drift (§5.1.4).
65
+ if (keychainGroup.length > 0) {
66
+ config.cacheConfig.keychainSharingGroup = keychainGroup;
67
+ }
68
+
69
+ NSError *clientError = nil;
70
+ MSALPublicClientApplication *client =
71
+ [[MSALPublicClientApplication alloc] initWithConfiguration:config error:&clientError];
72
+ if (client == nil) {
73
+ if (error != NULL) {
74
+ // The usual cause is a redirect URI that does not match the required
75
+ // `msauth.<bundle id>` format, or a missing keychain-sharing entitlement — both
76
+ // were real failures on device before the example app was fixed (§5.1.2).
77
+ *error = [RNIntuneCore
78
+ errorWithCode:RNIntuneErrorNative
79
+ message:[NSString
80
+ stringWithFormat:@"MSAL could not be initialised: %@",
81
+ clientError.localizedDescription
82
+ ?: @"unknown reason"]];
83
+ }
84
+ return NO;
85
+ }
86
+
87
+ _client = client;
88
+ return YES;
89
+ }
90
+
91
+ - (void)invalidate
92
+ {
93
+ _client = nil;
94
+ }
95
+
96
+ - (BOOL)isConfigured
97
+ {
98
+ return _client != nil;
99
+ }
100
+
101
+ #pragma mark - Sign-in
102
+
103
+ - (void)signInWithScopes:(NSArray<NSString *> *)scopes
104
+ loginHint:(NSString *)loginHint
105
+ prompt:(NSString *)prompt
106
+ presentingController:(UIViewController *)controller
107
+ completion:(RNIntuneAuthCompletion)completion
108
+ {
109
+ MSALPublicClientApplication *client = _client;
110
+ if (client == nil) {
111
+ completion(nil, [self notConfiguredError]);
112
+ return;
113
+ }
114
+
115
+ MSALWebviewParameters *webParams =
116
+ [[MSALWebviewParameters alloc] initWithAuthPresentationViewController:controller];
117
+
118
+ MSALInteractiveTokenParameters *params =
119
+ [[MSALInteractiveTokenParameters alloc] initWithScopes:[self resolveScopes:scopes]
120
+ webviewParameters:webParams];
121
+ params.promptType = [self promptTypeFromString:prompt];
122
+ if (loginHint.length > 0) {
123
+ params.loginHint = loginHint;
124
+ }
125
+
126
+ // MSAL requires the interactive call on the main thread, and it presents UI.
127
+ dispatch_async(dispatch_get_main_queue(), ^{
128
+ [client acquireTokenWithParameters:params
129
+ completionBlock:^(MSALResult *result, NSError *error) {
130
+ [self complete:completion result:result error:error];
131
+ }];
132
+ });
133
+ }
134
+
135
+ - (void)signInSilentWithScopes:(NSArray<NSString *> *)scopes
136
+ accountId:(NSString *)accountId
137
+ completion:(RNIntuneAuthCompletion)completion
138
+ {
139
+ [self acquireTokenWithScopes:scopes
140
+ accountId:accountId
141
+ forceRefresh:NO
142
+ completion:completion];
143
+ }
144
+
145
+ - (void)acquireTokenWithScopes:(NSArray<NSString *> *)scopes
146
+ accountId:(NSString *)accountId
147
+ forceRefresh:(BOOL)forceRefresh
148
+ completion:(RNIntuneAuthCompletion)completion
149
+ {
150
+ MSALPublicClientApplication *client = _client;
151
+ if (client == nil) {
152
+ completion(nil, [self notConfiguredError]);
153
+ return;
154
+ }
155
+
156
+ NSError *lookupError = nil;
157
+ MSALAccount *account = [self accountForId:accountId error:&lookupError];
158
+ if (account == nil) {
159
+ // Not a fault. With no cached account there is nothing to refresh silently, and the
160
+ // caller's next move is the same as for an expired token: sign in interactively.
161
+ completion(nil,
162
+ lookupError ?: [RNIntuneCore
163
+ errorWithCode:RNIntuneErrorInteractionRequired
164
+ message:@"No signed-in account is cached. Call "
165
+ @"signIn to acquire one."]);
166
+ return;
167
+ }
168
+
169
+ MSALSilentTokenParameters *params =
170
+ [[MSALSilentTokenParameters alloc] initWithScopes:[self resolveScopes:scopes]
171
+ account:account];
172
+ params.forceRefresh = forceRefresh;
173
+
174
+ [client acquireTokenSilentWithParameters:params
175
+ completionBlock:^(MSALResult *result, NSError *error) {
176
+ [self complete:completion result:result error:error];
177
+ }];
178
+ }
179
+
180
+ #pragma mark - Accounts
181
+
182
+ - (NSArray<NSDictionary<NSString *, id> *> *)accountsWithError:(NSError **)error
183
+ {
184
+ MSALPublicClientApplication *client = _client;
185
+ if (client == nil) {
186
+ if (error != NULL) {
187
+ *error = [self notConfiguredError];
188
+ }
189
+ return nil;
190
+ }
191
+
192
+ NSError *msalError = nil;
193
+ NSArray<MSALAccount *> *accounts = [client allAccounts:&msalError];
194
+ if (accounts == nil) {
195
+ if (error != NULL) {
196
+ *error = [RNIntuneCore errorWithCode:RNIntuneErrorNative
197
+ message:msalError.localizedDescription
198
+ ?: @"MSAL could not list accounts."];
199
+ }
200
+ return nil;
201
+ }
202
+
203
+ NSMutableArray<NSDictionary<NSString *, id> *> *out =
204
+ [NSMutableArray arrayWithCapacity:accounts.count];
205
+ for (MSALAccount *account in accounts) {
206
+ [out addObject:@{
207
+ @"accountId" : [self accountIdFor:account] ?: @"",
208
+ @"tenantId" : account.homeAccountId.tenantId ?: @"",
209
+ @"username" : account.username ?: @"",
210
+ }];
211
+ }
212
+ return out;
213
+ }
214
+
215
+ - (BOOL)removeAccountId:(NSString *)accountId error:(NSError **)error
216
+ {
217
+ MSALPublicClientApplication *client = _client;
218
+ if (client == nil) {
219
+ if (error != NULL) {
220
+ *error = [self notConfiguredError];
221
+ }
222
+ return NO;
223
+ }
224
+
225
+ NSError *lookupError = nil;
226
+ MSALAccount *account = [self accountForId:accountId error:&lookupError];
227
+ if (account == nil) {
228
+ // Already gone is success. `reset` runs this after the SDK has unregistered, and it
229
+ // must be safe to retry from the journal on the next launch (SPEC §7).
230
+ if (lookupError != nil && error != NULL) {
231
+ *error = lookupError;
232
+ return NO;
233
+ }
234
+ return YES;
235
+ }
236
+
237
+ NSError *removeError = nil;
238
+ if (![client removeAccount:account error:&removeError]) {
239
+ if (error != NULL) {
240
+ *error = [RNIntuneCore errorWithCode:RNIntuneErrorNative
241
+ message:removeError.localizedDescription
242
+ ?: @"MSAL could not remove the account."];
243
+ }
244
+ return NO;
245
+ }
246
+ return YES;
247
+ }
248
+
249
+ - (void)removeAllAccounts
250
+ {
251
+ MSALPublicClientApplication *client = _client;
252
+ if (client == nil) {
253
+ return;
254
+ }
255
+
256
+ NSArray<MSALAccount *> *accounts = [client allAccounts:NULL];
257
+ for (MSALAccount *account in accounts) {
258
+ // Errors are deliberately not propagated: this runs inside the reset sequence, where
259
+ // the journal's verification decides whether the reset took, not this loop.
260
+ [client removeAccount:account error:NULL];
261
+ }
262
+ }
263
+
264
+ #pragma mark - Helpers
265
+
266
+ /**
267
+ * Finds the account by the id this module hands out.
268
+ *
269
+ * That id is the Entra object ID, not MSAL's own `identifier` (which is
270
+ * `<objectId>.<tenantId>`), because the Intune SDK's `registerAndEnrollAccountId:` wants
271
+ * the object ID — one value has to serve both, so the narrower one wins. Matching is done
272
+ * over `allAccounts` rather than `accountForIdentifier:` for the same reason: that lookup
273
+ * takes MSAL's composite identifier, which is not what we store.
274
+ */
275
+ - (MSALAccount *)accountForId:(NSString *)accountId error:(NSError **)error
276
+ {
277
+ MSALPublicClientApplication *client = _client;
278
+ NSError *msalError = nil;
279
+ NSArray<MSALAccount *> *accounts = [client allAccounts:&msalError];
280
+ if (accounts == nil) {
281
+ if (error != NULL) {
282
+ *error = [RNIntuneCore errorWithCode:RNIntuneErrorNative
283
+ message:msalError.localizedDescription
284
+ ?: @"MSAL could not list accounts."];
285
+ }
286
+ return nil;
287
+ }
288
+
289
+ if (accountId.length == 0) {
290
+ // Single identity is decided (SPEC §9), so "the account" is unambiguous when there is
291
+ // one. Callers that pass nothing get it rather than an argument error.
292
+ return accounts.firstObject;
293
+ }
294
+
295
+ for (MSALAccount *account in accounts) {
296
+ if ([[self accountIdFor:account] isEqualToString:accountId]) {
297
+ return account;
298
+ }
299
+ }
300
+ return nil;
301
+ }
302
+
303
+ - (NSString *)accountIdFor:(MSALAccount *)account
304
+ {
305
+ return account.homeAccountId.objectId;
306
+ }
307
+
308
+ - (NSArray<NSString *> *)resolveScopes:(NSArray<NSString *> *)scopes
309
+ {
310
+ return scopes.count > 0 ? scopes : RNIntuneAuth.defaultScopes;
311
+ }
312
+
313
+ - (MSALPromptType)promptTypeFromString:(NSString *)prompt
314
+ {
315
+ if ([prompt isEqualToString:@"selectAccount"]) {
316
+ return MSALPromptTypeSelectAccount;
317
+ }
318
+ if ([prompt isEqualToString:@"login"]) {
319
+ return MSALPromptTypeLogin;
320
+ }
321
+ if ([prompt isEqualToString:@"consent"]) {
322
+ return MSALPromptTypeConsent;
323
+ }
324
+ if ([prompt isEqualToString:@"whenRequired"]) {
325
+ return MSALPromptTypePromptIfNecessary;
326
+ }
327
+ // Including nil. An unknown value must not fail a sign-in: a string added to the JS
328
+ // enum later would otherwise break every already-shipped native binary.
329
+ return MSALPromptTypeDefault;
330
+ }
331
+
332
+ - (NSError *)notConfiguredError
333
+ {
334
+ return [RNIntuneCore errorWithCode:RNIntuneErrorNotConfigured
335
+ message:@"MSAL is not configured. Call configure first."];
336
+ }
337
+
338
+ /// Shapes an `AuthResult`, or maps MSAL's error onto a stable code. The access token here
339
+ /// is for the app's own scopes; the MAM token never passes through (CLAUDE.md rule 9).
340
+ - (void)complete:(RNIntuneAuthCompletion)completion
341
+ result:(MSALResult *)result
342
+ error:(NSError *)error
343
+ {
344
+ if (result != nil) {
345
+ completion(@{
346
+ @"accountId" : [self accountIdFor:result.account] ?: @"",
347
+ @"tenantId" : result.account.homeAccountId.tenantId ?: @"",
348
+ @"username" : result.account.username ?: @"",
349
+ @"accessToken" : result.accessToken,
350
+ @"idToken" : result.idToken ?: NSNull.null,
351
+ // Unix seconds, matching AuthResult in SPEC §13.1.1.
352
+ @"expiresOn" : @(result.expiresOn.timeIntervalSince1970),
353
+ @"scopes" : result.scopes,
354
+ },
355
+ nil);
356
+ return;
357
+ }
358
+
359
+ completion(nil, [self mapError:error]);
360
+ }
361
+
362
+ - (NSError *)mapError:(NSError *)error
363
+ {
364
+ if (error == nil) {
365
+ return [RNIntuneCore errorWithCode:RNIntuneErrorNative
366
+ message:@"MSAL returned neither a result nor an error."];
367
+ }
368
+
369
+ if ([error.domain isEqualToString:MSALErrorDomain]) {
370
+ switch ((MSALError)error.code) {
371
+ case MSALErrorInteractionRequired:
372
+ return [RNIntuneCore
373
+ errorWithCode:RNIntuneErrorInteractionRequired
374
+ message:@"A prompt is required. Call signIn instead of signInSilent."];
375
+ case MSALErrorUserCanceled:
376
+ return [RNIntuneCore errorWithCode:RNIntuneErrorUserCancelled
377
+ message:@"The user dismissed the sign-in UI."];
378
+ default:
379
+ break;
380
+ }
381
+ }
382
+
383
+ // Everything else keeps MSAL's own description, which names the cause far better than
384
+ // a re-worded guess would. No token or claim is ever part of it.
385
+ return [RNIntuneCore errorWithCode:RNIntuneErrorNative
386
+ message:error.localizedDescription
387
+ ?: @"MSAL failed with no description."];
388
+ }
389
+
390
+ @end
@@ -0,0 +1,150 @@
1
+ //
2
+ // Pure Objective-C. Everything that talks to the Intune MAM SDK lives on this side of
3
+ // the boundary; RNIntune.mm is ObjC++ only because Codegen conformance and
4
+ // getTurboModule: are C++ (SPEC §5.1.1, CLAUDE.md rule 7).
5
+ //
6
+ // Keep it that way. An enrollment failure should be debuggable across one language
7
+ // boundary, not two, in a domain with no official React Native support.
8
+ //
9
+
10
+ #import <Foundation/Foundation.h>
11
+
12
+ #import "RNIntuneAuth.h"
13
+
14
+ NS_ASSUME_NONNULL_BEGIN
15
+
16
+ /// Stable rejection codes (SPEC §13.6). Never surface a raw platform error to JS.
17
+ extern NSString *const RNIntuneErrorNotConfigured;
18
+ extern NSString *const RNIntuneErrorResetRequired;
19
+ extern NSString *const RNIntuneErrorSDKUnavailable;
20
+ extern NSString *const RNIntuneErrorInvalidAccountId;
21
+ extern NSString *const RNIntuneErrorNotNeeded;
22
+ extern NSString *const RNIntuneErrorExternalAuthMode;
23
+ extern NSString *const RNIntuneErrorNative;
24
+ extern NSString *const RNIntuneErrorTokenProviderFailed;
25
+ extern NSString *const RNIntuneErrorTokenProviderMissing;
26
+ extern NSString *const RNIntuneErrorResetInProgress;
27
+ /// MSAL outcomes that are ordinary control flow, not faults (SPEC §13.6).
28
+ extern NSString *const RNIntuneErrorInteractionRequired;
29
+ extern NSString *const RNIntuneErrorUserCancelled;
30
+ /// Raised by the configure-time assertions below. Not in SPEC §13.6 yet — see §12.7 S1.
31
+ extern NSString *const RNIntuneErrorPlistConflict;
32
+
33
+ /// Event names. Must match the `IntuneEvents` keys in src/types.ts.
34
+ extern NSString *const RNIntuneEventEnrollmentResult;
35
+ extern NSString *const RNIntuneEventPolicyChanged;
36
+ extern NSString *const RNIntuneEventUnenrollmentResult;
37
+ extern NSString *const RNIntuneEventWipeRequested;
38
+ extern NSString *const RNIntuneEventRestartRequired;
39
+ extern NSString *const RNIntuneEventTokenRequest;
40
+ extern NSString *const RNIntuneEventBrokerStatusChanged;
41
+
42
+ /// Resolved configuration. `index.ts` applies every default, so nothing here is optional.
43
+ @interface RNIntuneConfig : NSObject
44
+ @property (nonatomic, copy) NSString *clientId;
45
+ @property (nonatomic, copy) NSString *tenantId;
46
+ @property (nonatomic, copy) NSString *authority;
47
+ @property (nonatomic, copy) NSString *redirectUri;
48
+ @property (nonatomic, copy) NSString *authMode;
49
+ @property (nonatomic, copy) NSString *maxFileProtectionLevel;
50
+ /// Empty string means "use the platform default" (`com.microsoft.adalcache`).
51
+ @property (nonatomic, copy) NSString *keychainGroupOverride;
52
+ @property (nonatomic) BOOL verboseLogging;
53
+ @property (nonatomic) BOOL restartHandledByApp;
54
+ @property (nonatomic) BOOL telemetryEnabled;
55
+ /// Hex strings for the SDK's own screens; empty means "leave Microsoft's default".
56
+ @property (nonatomic, copy) NSString *brandingBackground;
57
+ @property (nonatomic, copy) NSString *brandingForeground;
58
+ @property (nonatomic, copy) NSString *brandingAccent;
59
+ @property (nonatomic, copy) NSString *brandingSecondaryBackground;
60
+ @property (nonatomic, copy) NSString *brandingSecondaryForeground;
61
+ @end
62
+
63
+ @interface RNIntuneCore : NSObject
64
+
65
+ + (instancetype)shared;
66
+
67
+ /// Set once, before configure. Publishes SDK events to JS.
68
+ - (void)setEventSink:(void (^)(NSString *event, NSDictionary *body))sink;
69
+
70
+ /// YES when the MAM SDK is actually linked into the binary. Checked by class lookup so a
71
+ /// misbuilt binary degrades instead of crashing.
72
+ @property (nonatomic, readonly) BOOL sdkAvailable;
73
+
74
+ @property (nonatomic, readonly, getter=isConfigured) BOOL configured;
75
+ @property (nonatomic, readonly, nullable) NSString *configuredTenantId;
76
+
77
+ /// NO in `authMode: 'external'`, where the host app owns MSAL and the module performs no
78
+ /// sign-in at all (SPEC §3.2).
79
+ @property (nonatomic, readonly) BOOL builtinAuth;
80
+
81
+ /// MSAL. Configured only in `builtin` mode; `isConfigured` is NO otherwise.
82
+ @property (nonatomic, readonly) RNIntuneAuth *auth;
83
+
84
+ /// Applies the runtime overrides, installs the delegates, and runs the configure-time
85
+ /// assertions. Returns NO and fills `error` on `E_RESET_REQUIRED` (different tenant),
86
+ /// `E_SDK_UNAVAILABLE`, or `E_PLIST_CONFLICT`.
87
+ - (BOOL)applyConfig:(RNIntuneConfig *)config error:(NSError *_Nullable *_Nullable)error;
88
+
89
+ /// BrokerStatus (SPEC §13.1). Answerable before `configure`, on purpose: the app needs
90
+ /// it to decide whether to prompt for a broker install.
91
+ - (NSDictionary<NSString *, id> *)brokerStatus;
92
+
93
+ /// IntuneState (SPEC §4.2). Never rejects — reporting `configured: false` is the whole
94
+ /// point of the reconciliation primitive.
95
+ - (NSDictionary<NSString *, id> *)state;
96
+
97
+ /// Diagnostics (SPEC §13.3). No tokens, no UPNs — safe to attach to a support ticket.
98
+ - (NSDictionary<NSString *, NSString *> *)diagnostics;
99
+
100
+ #pragma mark - Enrollment
101
+
102
+ /**
103
+ * Registers and enrolls the account, completing with an `EnrollmentResult`.
104
+ *
105
+ * `registerAndEnrollAccountId:` returns immediately and says nothing; the outcome arrives
106
+ * later on `enrollmentRequestWithStatus:`. So the completion is held against the account
107
+ * ID and fired from the delegate (SPEC §12.5) — never from the call returning.
108
+ *
109
+ * Completes for every outcome, including failures: a non-success status is data, not an
110
+ * error. If the SDK says nothing at all within the timeout it completes with `pending`,
111
+ * which is truthful — the SDK keeps retrying on its own schedule and the result will
112
+ * still arrive as an event.
113
+ */
114
+ - (void)enrollAccountId:(NSString *)accountId
115
+ completion:(void (^)(NSDictionary<NSString *, id> *result))completion;
116
+
117
+ /// PolicySnapshot (SPEC §4.3). Nil when the SDK is not linked.
118
+ - (nullable NSDictionary<NSString *, id> *)policySnapshot;
119
+
120
+ #pragma mark - Reset (SPEC §7)
121
+
122
+ /**
123
+ * Writes the journal, then unregisters and unenrolls.
124
+ *
125
+ * **Blocks** while the SDK acquires the Intune AAD token, so it must not run on the main
126
+ * thread, and it must happen before the host app purges the account's Entra tokens
127
+ * (SPEC §5.3). The process may not survive it; everything after is driven by the journal.
128
+ */
129
+ - (void)resetWithWipe:(BOOL)wipe reason:(NSString *)reason;
130
+
131
+ /// Verifies the account is really gone and closes the journal. Returns NO and leaves the
132
+ /// journal open when it is not, so the next launch retries rather than declaring success.
133
+ - (BOOL)completeReset;
134
+
135
+ /// iOS-only interactive enrollment: the SDK runs the sign-in and shows its own UI.
136
+ - (void)enrollInteractiveWithUpn:(nullable NSString *)upn
137
+ completion:(void (^)(NSDictionary<NSString *, id> *result))completion;
138
+
139
+ #pragma mark - Token bridge (SPEC §13.4)
140
+
141
+ /// Answers a pending `tokenRequest`. The token goes to the SDK and never back to JS.
142
+ - (void)resolveTokenRequest:(NSString *)requestId token:(NSString *)token;
143
+ - (void)rejectTokenRequest:(NSString *)requestId reason:(NSString *)reason;
144
+
145
+ /// Builds an NSError carrying one of the stable codes above.
146
+ + (NSError *)errorWithCode:(NSString *)code message:(NSString *)message;
147
+
148
+ @end
149
+
150
+ NS_ASSUME_NONNULL_END