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
package/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Artashes Bayazetyan and react-native-intune contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ This licence covers the code in this repository only. It does not cover the
26
+ Microsoft Intune App SDK, which this project wraps and does not include. See
27
+ NOTICE for what belongs to Microsoft and under which terms.
package/NOTICE ADDED
@@ -0,0 +1,49 @@
1
+ # NOTICE
2
+
3
+ `react-native-intune` is MIT licensed (see LICENSE) and covers **only the code in this
4
+ repository**. It wraps Microsoft software that it neither includes nor relicenses.
5
+
6
+ ## The Microsoft Intune App SDK is not part of this package
7
+
8
+ The SDK is Microsoft's, distributed under Microsoft's own licence terms, and is **not
9
+ included in this repository or in the published npm tarball**.
10
+
11
+ `vendor/` is gitignored and excluded from `package.json`'s `files`. `scripts/fetch-sdks.mjs`
12
+ downloads the pinned version at install time, from Microsoft's own releases, verifying a
13
+ recorded sha256 per artifact. Nothing about that arrangement grants anyone rights they did
14
+ not already have from Microsoft.
15
+
16
+ Using this package therefore means accepting Microsoft's terms for the SDK. They arrive
17
+ alongside the download:
18
+
19
+ | File | What it covers |
20
+ |---|---|
21
+ | `vendor/ios/Microsoft License Terms Intune App SDK for iOS.pdf` | the iOS SDK |
22
+ | `vendor/android/Microsoft License Terms Intune App SDK for Android.pdf` | the Android SDK |
23
+ | `vendor/ios/REDIST.txt` | which iOS binaries may be redistributed in *your* app |
24
+ | `vendor/ios/ThirdPartyNotices.txt` | the SDK's own third-party attributions |
25
+
26
+ Read `REDIST.txt` before shipping: it names the frameworks you are permitted to
27
+ redistribute inside an application, which is a narrower permission than redistributing the
28
+ SDK itself. This project relies on that permission and does not extend it.
29
+
30
+ ## Microsoft Authentication Library (MSAL)
31
+
32
+ MSAL is a declared dependency rather than a vendored one — the pod on iOS, the Gradle
33
+ artifact on Android — and is fetched from public registries in the normal way. It is
34
+ Microsoft's, under the MIT licence, Copyright (c) Microsoft Corporation.
35
+
36
+ The version is pinned in `sdk-versions.json`. The reason is in SPEC §3.1: the Intune SDK
37
+ does not carry its own MSAL, it drives the application's, so two MSAL versions in one
38
+ binary is a failure nobody debugs quickly.
39
+
40
+ ## Trademarks
41
+
42
+ Microsoft, Intune, Microsoft Entra, Microsoft 365 and Azure are trademarks of the
43
+ Microsoft group of companies. They appear here only to describe what this package
44
+ integrates with.
45
+
46
+ **This project is not affiliated with, endorsed by, or supported by Microsoft.** Microsoft
47
+ publishes no React Native support for the Intune App SDK, which is why this package exists
48
+ and why a meaningful part of its behaviour was established by reading the SDK's own headers
49
+ and running it on real devices rather than from documentation.
package/README.md ADDED
@@ -0,0 +1,164 @@
1
+ # react-native-intune
2
+
3
+ Microsoft Intune app protection for React Native — **app-level data protection, not device
4
+ management.** MSAL with broker support is included, so sign-in and enrollment work without
5
+ a second SDK.
6
+
7
+ **[Documentation](https://bayazetyan.github.io/react-native-intune/)** ·
8
+ [Getting started](https://bayazetyan.github.io/react-native-intune/docs/getting-started) ·
9
+ [Traps](https://bayazetyan.github.io/react-native-intune/docs/notes/traps) ·
10
+ [API reference](https://bayazetyan.github.io/react-native-intune/docs/reference)
11
+
12
+ > **Status: pre-alpha.** Implemented and verified on real devices against a real tenant,
13
+ > but not released. Expect breaking changes until 1.0.
14
+
15
+ *Not affiliated with, endorsed by, or sponsored by Microsoft. Microsoft, Intune and Entra
16
+ are trademarks of the Microsoft group of companies.*
17
+
18
+ ## What it does
19
+
20
+ An IT administrator in any customer tenant can target your app from their Intune console
21
+ and enforce an App Protection Policy on it: a PIN or biometric unlock, copy-paste
22
+ restrictions between managed and unmanaged apps, screenshot blocking, save-as and open-from
23
+ restrictions, encryption at rest, conditional launch rules, and a selective wipe that
24
+ removes corporate data and leaves personal data alone.
25
+
26
+ **The device does not need to be enrolled in Intune.** That is the point of MAM — the
27
+ boundary is drawn around one app, and the employee's phone stays theirs.
28
+
29
+ ## What it is not
30
+
31
+ It cannot do device management, and no configuration changes that: the SDK runs inside your
32
+ app's sandbox.
33
+
34
+ | | |
35
+ |---|---|
36
+ | App-level PIN, copy-paste, screenshots, selective wipe | ✅ This library |
37
+ | Full device wipe, device passcode, disk encryption | ❌ The customer's MDM |
38
+ | Per-app VPN, network inspection, kiosk mode, inventory | ❌ The customer's MDM |
39
+
40
+ If someone asks whether this gives them "Intune device control", the answer is no. It makes
41
+ your app a first-class Intune-managed app; their MDM handles the device.
42
+
43
+ ## Licensing — read before installing
44
+
45
+ **This library is MIT. The Microsoft Intune App SDK is not, and is not included here.**
46
+
47
+ The SDK is downloaded from Microsoft's own repositories by `fetch-sdks`. It is never
48
+ committed to this repository and never published in the npm package. Microsoft's terms
49
+ apply to it, they are separate from ours, and **reviewing and accepting them is your
50
+ responsibility**:
51
+
52
+ - [Intune App SDK for iOS](https://github.com/msintuneappsdk/ms-intune-app-sdk-ios)
53
+ - [Intune App SDK for Android](https://github.com/microsoftconnect/ms-intune-app-sdk-android)
54
+
55
+ [`NOTICE`](./NOTICE) is the full statement.
56
+
57
+ ## Requirements
58
+
59
+ | | |
60
+ |---|---|
61
+ | React Native | 0.74+, **New Architecture required** |
62
+ | iOS | **17.0+, Xcode 26+** — MAM SDK 21.x is built against them |
63
+ | Android | minSdk 24, Java 17, Gradle 8.11.1 / AGP 8.9.1 / Kotlin 2.1.21 |
64
+ | On the device | Company Portal on Android; Authenticator or Company Portal on iOS |
65
+ | In the tenant | An Entra app registration with the Intune MAM API permission granted |
66
+
67
+ ## Install
68
+
69
+ ```bash
70
+ npm install react-native-intune
71
+ npx react-native-intune fetch-sdks # accepts Microsoft's terms, downloads the SDKs
72
+ ```
73
+
74
+ Installing the package is the short part. **Most of this integration is changes to your own
75
+ app project** — `Info.plist`, entitlements, `AndroidManifest.xml`, your app module's
76
+ `build.gradle`, your `Application` class — and autolinking does not touch any of them.
77
+
78
+ **Expo:** add the config plugin and run `expo prebuild`. Nearly everything is applied for
79
+ you, including the `MAMApplication` change.
80
+
81
+ ```json
82
+ { "expo": { "plugins": [["react-native-intune", { "androidSignatureHash": "…" }]] } }
83
+ ```
84
+
85
+ **Bare React Native:** two commands, then a short manual remainder.
86
+
87
+ ```bash
88
+ npx react-native-intune doctor # reports what is missing, changes nothing
89
+ npx react-native-intune setup # applies what it can, shows a diff first
90
+ ```
91
+
92
+ Then follow [iOS setup](https://bayazetyan.github.io/react-native-intune/docs/setup/ios) or
93
+ [Android setup](https://bayazetyan.github.io/react-native-intune/docs/setup/android).
94
+
95
+ > **Three of those steps fail silently when missed** — the app builds, runs, and protects
96
+ > nothing while everyone believes protection is in place. The setup guides mark which, and
97
+ > `doctor` finds them.
98
+
99
+ ## Quick start
100
+
101
+ ```ts
102
+ import Intune, { EnrollmentStatus } from 'react-native-intune';
103
+
104
+ // Per-tenant, from your own backend — one build serves many customers.
105
+ await Intune.configure({
106
+ clientId: cfg.aadClientId,
107
+ tenantId: cfg.aadTenantId,
108
+ authority: cfg.aadAuthority,
109
+ redirectUri: cfg.aadRedirectUri,
110
+ });
111
+
112
+ const { enrollment } = await Intune.signInAndEnroll();
113
+
114
+ // Only 'failed' means block.
115
+ if (enrollment.status === EnrollmentStatus.Failed) {
116
+ blockCorporateData();
117
+ }
118
+ ```
119
+
120
+ ## Enrollment outcomes
121
+
122
+ `enroll()` **resolves** for every outcome — a failure is data, not an exception. It rejects
123
+ only for programming errors.
124
+
125
+ | Status | What your app must do |
126
+ |---|---|
127
+ | `succeeded` | Continue. Policy is in force |
128
+ | `notTargeted` | **Continue.** Nobody has aimed a policy at this app yet |
129
+ | `notLicensed` | **Continue.** The employee has no Intune licence and is still a legitimate employee |
130
+ | `failed` | Block access to corporate data until it succeeds |
131
+ | `pending` · `authorizationNeeded` · `wrongUser` · `companyPortalRequired` | Handle it — see the reference |
132
+ | `unenrolled` · `unenrollmentFailed` · `unknown` | Reset states, and one to treat conservatively |
133
+
134
+ > **The most common integration bug in libraries like this one** is treating anything that
135
+ > is not `succeeded` as "block the user". That breaks every customer with staff who have no
136
+ > Intune licence, and every pilot where the policy has not been targeted yet — while the app
137
+ > reports itself as secure. `notLicensed` and `notTargeted` mean the opposite of `failed`,
138
+ > and that distinction is prescribed by Microsoft rather than invented here.
139
+
140
+ [All eleven outcomes, and what to do with each](https://bayazetyan.github.io/react-native-intune/docs/guides/enrollment-outcomes)
141
+
142
+ ## Where the rest is
143
+
144
+ | | |
145
+ |---|---|
146
+ | [Traps and field notes](https://bayazetyan.github.io/react-native-intune/docs/notes/traps) | 23 things that each cost somebody a day and are in no Microsoft documentation |
147
+ | [Authentication](https://bayazetyan.github.io/react-native-intune/docs/guides/authentication) | The broker, MSAL, and using your own instead |
148
+ | [Reconcile at launch](https://bayazetyan.github.io/react-native-intune/docs/guides/reconcile-at-launch) | The pattern to drive enrollment from, and why not from lifecycle hooks |
149
+ | [Reset and wipe](https://bayazetyan.github.io/react-native-intune/docs/guides/reset-and-wipe) | One code path, several callers, and a process that may not survive it |
150
+ | [Troubleshooting](https://bayazetyan.github.io/react-native-intune/docs/troubleshooting) | The seven checks worth doing before opening an issue |
151
+ | [API reference](https://bayazetyan.github.io/react-native-intune/docs/reference) | Generated from the source |
152
+
153
+ ## Contributing
154
+
155
+ [How to contribute](https://bayazetyan.github.io/react-native-intune/docs/contributing/).
156
+ In short: nothing builds until you accept Microsoft's terms and run `fetch-sdks`, `vendor/`
157
+ is never committed, and a pull request touching native code states which platform was
158
+ actually run, on which device, against which tenant. Enrollment paths cannot be verified by
159
+ unit tests and CI does not pretend otherwise.
160
+
161
+ ## License
162
+
163
+ MIT — see [`LICENSE`](./LICENSE). It covers this library's code and not the Microsoft Intune
164
+ App SDK; [`NOTICE`](./NOTICE) says what belongs to whom.
@@ -0,0 +1,69 @@
1
+ require "json"
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
+
5
+ # The Microsoft SDKs are fetched, never committed (SPEC §2.1). Fail here with an
6
+ # instruction rather than letting the linker fail 200 lines deep.
7
+ vendor_ios = File.join(__dir__, "vendor", "ios")
8
+ unless File.directory?(vendor_ios) && !Dir.glob(File.join(vendor_ios, "*.xcframework")).empty?
9
+ raise "[react-native-intune] The Microsoft Intune App SDK is missing from vendor/ios. " \
10
+ "Run `yarn fetch-sdks` (or `node node_modules/react-native-intune/scripts/fetch-sdks.mjs`) " \
11
+ "and then `pod install` again."
12
+ end
13
+
14
+ Pod::Spec.new do |s|
15
+ s.name = "RNIntune"
16
+ s.version = package["version"]
17
+ s.summary = package["description"]
18
+ s.homepage = package["homepage"]
19
+ s.license = package["license"]
20
+ s.authors = package["author"]
21
+
22
+ # Deliberately NOT min_ios_version_supported. Intune App SDK 21.8.0 is built with
23
+ # `minos 17.0` (verified with otool on IntuneMAMSwift.framework), so a host app on
24
+ # React Native's floor of 15.1 cannot link it. Supporting iOS 16 means pinning SDK
25
+ # 20.x, which Microsoft maintains for high-priority security fixes only.
26
+ s.platforms = { :ios => "17.0" }
27
+ s.source = { :git => "https://github.com/bayazetyan/react-native-intune.git", :tag => "#{s.version}" }
28
+
29
+ # No .swift and no .cpp on purpose — see SPEC §5.1.1 for the language split.
30
+ s.source_files = "ios/**/*.{h,m,mm}"
31
+ s.private_header_files = "ios/**/*.h"
32
+
33
+ # IntuneMAMTelemetry is a separate product in 21.x and must be linked explicitly.
34
+ s.vendored_frameworks = [
35
+ "vendor/ios/IntuneMAMSwift.xcframework",
36
+ "vendor/ios/IntuneMAMSwiftStub.xcframework",
37
+ "vendor/ios/IntuneMAMTelemetry.xcframework"
38
+ ]
39
+
40
+ # Not optional. Carries PinViewController, the blur/policy/diagnostics/MTD-compliance
41
+ # screens and 28 localizations. Without it the SDK's UI cannot render — and that
42
+ # failure shows up at runtime, not at build time.
43
+ s.resources = ["vendor/ios/IntuneMAMResources.bundle"]
44
+
45
+ # Keeps IntuneMAMConfigurator (and Microsoft's licence files) in the installed pod so
46
+ # the consumer can call the configurator from an Xcode build phase.
47
+ s.preserve_paths = "vendor/**/*"
48
+
49
+ s.frameworks = "MessageUI", "Security", "CoreServices", "SystemConfiguration",
50
+ "ImageIO", "LocalAuthentication", "AudioToolbox", "QuartzCore",
51
+ "WebKit", "MetricKit"
52
+ s.libraries = "sqlite3", "c++"
53
+
54
+ # Required, and not only by our own auth layer. The Intune SDK does not carry its own
55
+ # MSAL — it drives the app's. Without this pod even loginAndEnrollAccount:, where the
56
+ # SDK runs the whole sign-in itself, fails with "Failed to instantiate MSALAuthority /
57
+ # Ensure the appropriate version of ADAL is included in the application" (observed on
58
+ # device, 2026-09-04). Version pinned in sdk-versions.json -> toolchain.msal_ios.
59
+ s.dependency "MSAL", "2.15.0"
60
+
61
+ s.pod_target_xcconfig = {
62
+ "STRIP_SWIFT_SYMBOLS" => "NO",
63
+ "ENABLE_BITCODE" => "NO"
64
+ }
65
+
66
+ # RN 0.74+ helper: wires Codegen and the New Architecture dependencies. Do not
67
+ # hand-roll React-Core / folly deps or RCT_NEW_ARCH_ENABLED flags.
68
+ install_modules_dependencies(s)
69
+ end
@@ -0,0 +1,152 @@
1
+ buildscript {
2
+ // The MAM SDK compatibility matrix (SPEC §6.1) is tested as whole rows, not as a
3
+ // mix. The pinned Android tag in sdk-lock.json is 12.4.0, so this is the 12.0.0
4
+ // row: Android 16 (compileSdk 36), Gradle 8.11.1, AGP 8.9.1, Kotlin 2.1.21, Java 17.
5
+ // Mirrored in sdk-versions.json -> toolchain.requires; change both together.
6
+ ext.Intune = [
7
+ kotlinVersion: "2.1.21",
8
+ minSdkVersion: 24,
9
+ compileSdkVersion: 36
10
+ ]
11
+
12
+ ext.getExtOrDefault = { prop ->
13
+ if (rootProject.ext.has(prop)) {
14
+ return rootProject.ext.get(prop)
15
+ }
16
+
17
+ return Intune[prop]
18
+ }
19
+
20
+ repositories {
21
+ google()
22
+ // Not jcenter(), which Microsoft's docs still reference — it is read-only/retired.
23
+ mavenCentral()
24
+ }
25
+
26
+ dependencies {
27
+ classpath "com.android.tools.build:gradle:8.9.1"
28
+ // noinspection DifferentKotlinGradleVersion
29
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
30
+ }
31
+ }
32
+
33
+
34
+ apply plugin: "com.android.library"
35
+ apply plugin: "kotlin-android"
36
+
37
+ apply plugin: "com.facebook.react"
38
+
39
+ // The MAM Gradle plugin ("com.microsoft.intune.mam") is deliberately NOT applied here.
40
+ // It rewrites bytecode across the whole application and every one of its dependencies,
41
+ // so it belongs in the consumer's app module. Applying it in this library would rewrite
42
+ // only the library, build successfully, and protect nothing — the worst kind of failure.
43
+
44
+ android {
45
+ namespace "com.reactnativeintune"
46
+
47
+ compileSdkVersion getExtOrDefault("compileSdkVersion")
48
+
49
+ defaultConfig {
50
+ minSdkVersion getExtOrDefault("minSdkVersion")
51
+
52
+ // Shipped to consumers, because a release build with R8 fails without them and only
53
+ // a release build does — debug and unminified release both succeed, so an app finds
54
+ // out when it ships. See the file for what each rule is for.
55
+ consumerProguardFiles "consumer-rules.pro"
56
+ }
57
+
58
+ compileOptions {
59
+ sourceCompatibility JavaVersion.VERSION_17
60
+ targetCompatibility JavaVersion.VERSION_17
61
+ }
62
+
63
+ kotlinOptions {
64
+ jvmTarget = "17"
65
+ }
66
+ }
67
+
68
+ // Fetched by scripts/fetch-sdks.mjs into a gitignored vendor/ (SPEC §2.1).
69
+ //
70
+ // Resolved from projectDir, NOT rootDir. SPEC §12.3 and TODO.md both write
71
+ // "$rootDir/../vendor/...", but when this library is autolinked, rootDir is the
72
+ // *consumer app's* android/ directory — that path would point at <app>/vendor and
73
+ // never resolve. projectDir is this library's own android/ folder, so ../vendor is
74
+ // the package root where fetch-sdks writes.
75
+ def mamAar = file("$projectDir/../vendor/android/Microsoft.Intune.MAM.SDK.aar")
76
+
77
+ // Parallel to the raise in RNIntune.podspec: fail with an instruction rather than an
78
+ // unresolved-symbol error deep in the Kotlin compile. Scoped to graphs that actually
79
+ // compile this library, so `clean` and unrelated tasks are not blocked by a missing
80
+ // download.
81
+ gradle.taskGraph.whenReady { graph ->
82
+ if (mamAar.exists()) return
83
+ def compiling = graph.allTasks.any {
84
+ it.project == project && it.name.startsWith("compile")
85
+ }
86
+ if (compiling) {
87
+ throw new GradleException(
88
+ "[react-native-intune] The Microsoft Intune App SDK is missing from vendor/android.\n" +
89
+ " Expected: ${mamAar}\n" +
90
+ " Run: node node_modules/react-native-intune/scripts/fetch-sdks.mjs"
91
+ )
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Disable AAR packaging for this library, with a message that says why.
97
+ *
98
+ * `./gradlew assembleDebug` from a consumer's android/ directory assembles every module,
99
+ * including this one, and `:react-native-intune:bundleDebugAar` then fails with "Direct
100
+ * local .aar file dependencies are not supported when building an AAR". People run that
101
+ * command, and the error names our library, so it reads as our bug.
102
+ *
103
+ * It is not a workaround for a problem we could otherwise solve. AGP's own message says
104
+ * the AAR "would be broken because the classes and Android resources from any local .aar
105
+ * file dependencies would not be packaged" — so the output being skipped is an output
106
+ * that could never have been correct. The MAM SDK is distributed as a file from
107
+ * Microsoft's GitHub, not from Maven Central, so there is no coordinate to depend on
108
+ * instead.
109
+ *
110
+ * Nothing is lost: autolinking consumes this library as a Gradle *project*, so its AAR is
111
+ * never built for a consumer. `:app:assembleDebug` was always the working form; now the
112
+ * root form works too.
113
+ */
114
+ tasks.configureEach { task ->
115
+ if (task.name ==~ /bundle.*Aar/) {
116
+ task.enabled = false
117
+ task.doFirst {
118
+ logger.lifecycle(
119
+ "[react-native-intune] Skipping ${task.name}: this library depends on the MAM " +
120
+ "SDK as a local .aar, so AGP cannot package a valid AAR for it. Consumers " +
121
+ "autolink it as a Gradle project and never need one."
122
+ )
123
+ }
124
+ }
125
+ }
126
+
127
+ dependencies {
128
+ implementation "com.facebook.react:react-android"
129
+
130
+ implementation files(mamAar)
131
+
132
+ // MSAL. Mirrored in sdk-versions.json -> toolchain.msal_android; change both together.
133
+ //
134
+ // Unlike iOS, Microsoft states no required version for Android — the SDK guide says
135
+ // only "integrate MSAL". So this pin is ours, for reproducibility rather than
136
+ // compatibility, and it is exact for the same reason the iOS one is: two MSAL versions
137
+ // in one binary is a failure mode nobody debugs quickly.
138
+ //
139
+ // mavenCentral, never jcenter — Microsoft's own docs still say jcenter in places and it
140
+ // has been read-only for years (CLAUDE.md, Android gotchas).
141
+ // `display-mask` is excluded deliberately. MSAL depends on it for dual-screen Surface
142
+ // Duo layout, and it is published only to Microsoft's own Azure DevOps feed, not Maven
143
+ // Central. MSAL's README tells apps to add that feed — but repositories are declared by
144
+ // the *consumer's* settings.gradle, so a library cannot add one, and requiring every
145
+ // consumer to trust an extra feed is a poor trade for dual-screen support.
146
+ //
147
+ // [verify] whether MSAL degrades cleanly without it, or throws at sign-in on a real
148
+ // device. If it throws, the fallback is documenting the feed for consumers.
149
+ implementation("com.microsoft.identity.client:msal:8.4.2") {
150
+ exclude group: "com.microsoft.device.display"
151
+ }
152
+ }
@@ -0,0 +1,28 @@
1
+ # ProGuard/R8 rules shipped to consumers of this library.
2
+ #
3
+ # Wired through `consumerProguardFiles`, so an app that enables minification gets them
4
+ # without having to discover any of this. It shipped broken otherwise: a release build
5
+ # with R8 fails outright, and only a release build — every debug build and the unminified
6
+ # release both succeed, so this is invisible until someone ships.
7
+ #
8
+ # All three entries are `-dontwarn`, not `-keep`. Nothing here is called at runtime on the
9
+ # paths this module uses; the classes are referenced from code branches that never execute,
10
+ # and R8 refuses to finish while it cannot resolve a reference it can see.
11
+
12
+ # `nimbus-jose-jwt`, MSAL's JWT library, has optional support for BouncyCastle and Google
13
+ # Tink and references both unconditionally. Neither is a declared dependency of MSAL, and
14
+ # MSAL's own AAR ships no ProGuard rules at all — verified by unpacking it — so the gap
15
+ # lands on whoever brings MSAL in. That is us.
16
+ -dontwarn org.bouncycastle.**
17
+ -dontwarn com.google.crypto.tink.**
18
+
19
+ # `com.microsoft.device.display:display-mask` is excluded from the MSAL dependency on
20
+ # purpose (SPEC §6.1.2): it is published only to Microsoft's own Azure DevOps feed and a
21
+ # library cannot add a repository on its consumers' behalf. MSAL references it from
22
+ # `DualScreenActivity.getHinge`, for Surface Duo dual-screen layout, which is a path this
23
+ # module never takes.
24
+ #
25
+ # This is the cost of that exclusion, and it only appeared here — sign-in and enrollment
26
+ # both work without the artifact, so the `[verify]` note in §6.1.2 was answered by a
27
+ # release build rather than by a device.
28
+ -dontwarn com.microsoft.device.display.**
@@ -0,0 +1,2 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ </manifest>