@chipmobilesdk/rn-auth 0.3.0 → 0.4.0
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/CHANGELOG.md +239 -113
- package/README.md +221 -190
- package/package.json +72 -54
- package/skills/sdk-rn-auth/SKILL.md +65 -63
- package/src/access/accessTier.ts +88 -88
- package/src/app-auth.ts +6 -0
- package/src/config/types.ts +154 -154
- package/src/config/validateConfig.ts +114 -108
- package/src/core/authMachine.ts +380 -364
- package/src/core/profile.ts +57 -60
- package/src/core/session.ts +105 -112
- package/src/diagnostics/errors.ts +99 -85
- package/src/diagnostics/messageKeys.ts +72 -61
- package/src/index.ts +72 -83
- package/src/keychain.ts +6 -0
- package/src/oidc/authClient.ts +236 -199
- package/src/oidc/classifyError.ts +76 -76
- package/src/oidc/socialRouting.ts +66 -73
- package/src/react/AuthProvider.tsx +30 -47
- package/src/react/hooks.ts +103 -91
- package/src/testing/conformance.ts +177 -0
- package/src/testing/index.ts +30 -0
- package/src/tokens/accessToken.ts +159 -164
- package/src/tokens/secureStore.ts +85 -52
package/README.md
CHANGED
|
@@ -1,190 +1,221 @@
|
|
|
1
|
-
# @chipmobilesdk/rn-auth
|
|
2
|
-
|
|
3
|
-
Reusable Microsoft Entra External ID authentication for ChipMobileSdk-family
|
|
4
|
-
React Native apps. The library is a **public OAuth2/OIDC client** (Authorization
|
|
5
|
-
Code + PKCE, **no backend, no client secret**). Android presents **Continue with
|
|
6
|
-
Google**, iOS presents **Continue with Apple**, and either platform can also
|
|
7
|
-
present **Continue with Facebook**; all start the same External ID
|
|
8
|
-
sign-up/sign-in user flow, routed to the right social provider with a
|
|
9
|
-
`domain_hint`. Google, Apple, and Facebook are federated **inside the External ID
|
|
10
|
-
tenant**, so the app embeds no native social SDK and no Sign in with Apple
|
|
11
|
-
entitlement. Each platform renders all of its configured providers as separate
|
|
12
|
-
buttons in configuration order.
|
|
13
|
-
|
|
14
|
-
> **License:** `UNLICENSED`. Published publicly for use by the owner's
|
|
15
|
-
> applications; no open-source license is granted.
|
|
16
|
-
|
|
17
|
-
- **Version**:
|
|
18
|
-
- **Entrypoint**: `@chipmobilesdk/rn-auth`
|
|
19
|
-
|
|
20
|
-
- Single active account, session restore, local + global sign-out.
|
|
21
|
-
- Per-resource delegated access tokens for Azure resources.
|
|
22
|
-
- Group/role/claim access-tier evaluation that **fails closed**.
|
|
23
|
-
- Tokens persist only in platform secure storage (Keychain / Keystore).
|
|
24
|
-
- No i18n runtime dependency: user-facing copy is stable keys + English defaults.
|
|
25
|
-
|
|
26
|
-
## Install (consuming app)
|
|
27
|
-
|
|
28
|
-
```sh
|
|
29
|
-
npm install @chipmobilesdk/rn-auth react-native-app-auth react-native-keychain
|
|
30
|
-
cd ios && pod install
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
`react`, `react-native`, `react-native-app-auth`, and `react-native-keychain`
|
|
34
|
-
are **peer dependencies**. The two native libraries are only required by the
|
|
35
|
-
default adapters — an app injecting custom ports may omit them.
|
|
36
|
-
|
|
37
|
-
See [native setup](../../specs/003-mobile-entra-auth/contracts/native-setup.md)
|
|
38
|
-
for the iOS `Info.plist` URL scheme and the Android `appAuthRedirectScheme`
|
|
39
|
-
Gradle placeholder.
|
|
40
|
-
|
|
41
|
-
## Quick start
|
|
42
|
-
|
|
43
|
-
```tsx
|
|
44
|
-
import {
|
|
45
|
-
AuthProvider,
|
|
46
|
-
createAuth,
|
|
47
|
-
createAppAuthClient,
|
|
48
|
-
createKeychainSecureStore,
|
|
49
|
-
useAuth,
|
|
50
|
-
useSignInProvider,
|
|
51
|
-
} from '@chipmobilesdk/rn-auth';
|
|
52
|
-
|
|
53
|
-
const auth = createAuth({
|
|
54
|
-
authority: 'https://<tenant>.ciamlogin.com/<tenant>.onmicrosoft.com',
|
|
55
|
-
clientId: '<public-client-id>',
|
|
56
|
-
redirectUrl: 'com.yourapp://oauthredirect',
|
|
57
|
-
scopes: ['openid', 'profile', 'offline_access'],
|
|
58
|
-
providers: [
|
|
59
|
-
{ id: 'google', platforms: ['android'], domainHint: 'google.com', labelKey: 'auth.action.continueGoogle' },
|
|
60
|
-
{ id: 'apple', platforms: ['ios'], domainHint: 'apple.com', labelKey: 'auth.action.continueApple' },
|
|
61
|
-
// Optional third provider, shown on both platforms after the platform-native one:
|
|
62
|
-
{ id: 'facebook', platforms: ['ios', 'android'], domainHint: 'facebook.com', labelKey: 'auth.action.continueFacebook' },
|
|
63
|
-
],
|
|
64
|
-
resources: [{ key: 'storage', scopes: ['https://storage.azure.com/user_impersonation'] }],
|
|
65
|
-
accessTierMapping: { premiumGroupObjectIds: ['<premium-group-object-id>'] },
|
|
66
|
-
secureStore: createKeychainSecureStore(),
|
|
67
|
-
authClient: createAppAuthClient(),
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
export const App = () => (
|
|
71
|
-
<AuthProvider auth={auth}>
|
|
72
|
-
<Screen />
|
|
73
|
-
</AuthProvider>
|
|
74
|
-
);
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
Hooks: `useAuth()` (state + `signIn`/`signOut`/`signOutGlobal`/`restore`/`requirePremium`),
|
|
78
|
-
`useProfile()`, `useAccessTier()`, `useAccessToken(resourceKey)`,
|
|
79
|
-
`useSignInProviders()` (all platform providers, in config order — map to one
|
|
80
|
-
button each) and `useSignInProvider()` (first available, for a single-button UI).
|
|
81
|
-
|
|
82
|
-
### Session lifecycle guarantees
|
|
83
|
-
|
|
84
|
-
- **Restore deletes the stored session only when the provider rejects the refresh
|
|
85
|
-
token** (`invalid_grant` and the equivalent AADSTS codes). A timeout, a 5xx or an
|
|
86
|
-
error the package cannot classify restores `offline`: cached profile, tier
|
|
87
|
-
unverified, retried on the next `restore()`.
|
|
88
|
-
- **A sign-out wins.** A token refresh still in flight when the user signs out is
|
|
89
|
-
discarded; it cannot write a token back or return the state to `authenticated`.
|
|
90
|
-
- **Rotated refresh tokens are persisted** as soon as they arrive, and concurrent
|
|
91
|
-
`requestAccessToken` calls for one resource share one network refresh.
|
|
92
|
-
- **`signOutGlobal()` returns `{ global: 'ended' | 'failed', error? }`.** Local state
|
|
93
|
-
is cleared either way; `failed` means the tenant session may still be alive.
|
|
94
|
-
|
|
95
|
-
## Configuration contract (LIB-010)
|
|
96
|
-
|
|
97
|
-
The library accepts **public values only**. Provider secrets, Apple keys, and
|
|
98
|
-
client secrets are configured in the External ID tenant, never in the app
|
|
99
|
-
([FR-017](../../specs/003-mobile-entra-auth/spec.md)).
|
|
100
|
-
|
|
101
|
-
| Section | Keys |
|
|
102
|
-
|---------|------|
|
|
103
|
-
| A — Tenant / client | `authority`, `clientId`, `redirectUrl`, `scopes` (include `offline_access`) |
|
|
104
|
-
| B — Android Google | `providers[google]`: `domainHint`, `platforms: ['android']`, `labelKey` |
|
|
105
|
-
| C — iOS Apple | `providers[apple]`: `domainHint`, `platforms: ['ios']`, `labelKey` |
|
|
106
|
-
| C2 — Facebook (optional) | `providers[facebook]`: `domainHint: 'facebook.com'`, `platforms: ['ios','android']`, `labelKey: 'auth.action.continueFacebook'`, optional `available` |
|
|
107
|
-
| D — Resources | `resources[].key`, `resources[].scopes`, `resources[].displayName?` |
|
|
108
|
-
| E — Access tier | `accessTierMapping.premiumGroupObjectIds` (+ optional role names / claim matchers; display names are diagnostics-only) |
|
|
109
|
-
| F — Ports | `secureStore` (required), `authClient` (optional), `messages` (optional copy override) |
|
|
110
|
-
|
|
111
|
-
Full contract: [auth-config.md](../../specs/003-mobile-entra-auth/contracts/auth-config.md)
|
|
112
|
-
and [public-api.md](../../specs/003-mobile-entra-auth/contracts/public-api.md).
|
|
113
|
-
|
|
114
|
-
## Tenant / provider prerequisite checklist (LIB-018)
|
|
115
|
-
|
|
116
|
-
These are **external** prerequisites (FR-013/FR-018) completed before the library
|
|
117
|
-
can sign users in:
|
|
118
|
-
|
|
119
|
-
**External ID tenant**
|
|
120
|
-
- [ ] Customer (CIAM) tenant created; sign-up/sign-in user flow configured.
|
|
121
|
-
- [ ] App registration created as a **public client**; redirect URI added (must match the native scheme, e.g. `com.yourapp://oauthredirect`).
|
|
122
|
-
- [ ] API permissions / scopes for each target Azure resource consented.
|
|
123
|
-
- [ ] Premium group(s) created; record the **group object id** (not the name).
|
|
124
|
-
- [ ] Groups (or roles) emitted in the token; plan for groups overage.
|
|
125
|
-
|
|
126
|
-
**Google (federated in the tenant)**
|
|
127
|
-
- [ ] Google Cloud OAuth client configured; client id/secret stored in the **tenant** IdP config (never in the app).
|
|
128
|
-
- [ ] Google added as an identity provider in the External ID user flow.
|
|
129
|
-
|
|
130
|
-
**Apple (federated in the tenant)**
|
|
131
|
-
- [ ] Apple Services ID + Sign in with Apple key configured; stored in the **tenant** IdP config.
|
|
132
|
-
- [ ] Apple added as an identity provider in the External ID user flow.
|
|
133
|
-
- [ ] Note: Apple sign-in operational credentials expire on a schedule and must be rotated tenant-side.
|
|
134
|
-
|
|
135
|
-
**Facebook (federated in the tenant — optional)**
|
|
136
|
-
- [ ] Facebook app created in Meta for Developers; **App ID + App Secret** stored in the **tenant** IdP config (never in the app).
|
|
137
|
-
- [ ] Facebook added as an identity provider in the External ID user flow; `domain_hint` confirmed (expected `facebook.com`).
|
|
138
|
-
- [ ] Facebook app OAuth redirect / valid OAuth domains match the tenant federation redirect.
|
|
139
|
-
- [ ] iOS: because Facebook is a third-party login, keep Sign in with Apple offered on iOS (Apple guideline 4.8).
|
|
140
|
-
- [ ] Update Apple App Privacy and Google Play Data Safety to include Facebook as an identity provider before release.
|
|
141
|
-
|
|
142
|
-
## Security & privacy
|
|
143
|
-
|
|
144
|
-
- Tokens and refresh artifacts persist only in `SecureTokenStore` (Keychain /
|
|
145
|
-
Keystore). Access tokens are kept in memory only.
|
|
146
|
-
- Access-tier decisions prefer stable group **object ids**; display names never
|
|
147
|
-
grant access; missing/overage claims fail closed.
|
|
148
|
-
- Diagnostics (`AuthError`) never contain secrets or token values.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
-
|
|
162
|
-
`
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
`
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
`
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
1
|
+
# @chipmobilesdk/rn-auth
|
|
2
|
+
|
|
3
|
+
Reusable Microsoft Entra External ID authentication for ChipMobileSdk-family
|
|
4
|
+
React Native apps. The library is a **public OAuth2/OIDC client** (Authorization
|
|
5
|
+
Code + PKCE, **no backend, no client secret**). Android presents **Continue with
|
|
6
|
+
Google**, iOS presents **Continue with Apple**, and either platform can also
|
|
7
|
+
present **Continue with Facebook**; all start the same External ID
|
|
8
|
+
sign-up/sign-in user flow, routed to the right social provider with a
|
|
9
|
+
`domain_hint`. Google, Apple, and Facebook are federated **inside the External ID
|
|
10
|
+
tenant**, so the app embeds no native social SDK and no Sign in with Apple
|
|
11
|
+
entitlement. Each platform renders all of its configured providers as separate
|
|
12
|
+
buttons in configuration order.
|
|
13
|
+
|
|
14
|
+
> **License:** `UNLICENSED`. Published publicly for use by the owner's
|
|
15
|
+
> applications; no open-source license is granted.
|
|
16
|
+
|
|
17
|
+
- **Version**: see [CHANGELOG](CHANGELOG.md)
|
|
18
|
+
- **Entrypoint**: `@chipmobilesdk/rn-auth`
|
|
19
|
+
|
|
20
|
+
- Single active account, session restore, local + global sign-out.
|
|
21
|
+
- Per-resource delegated access tokens for Azure resources.
|
|
22
|
+
- Group/role/claim access-tier evaluation that **fails closed**.
|
|
23
|
+
- Tokens persist only in platform secure storage (Keychain / Keystore).
|
|
24
|
+
- No i18n runtime dependency: user-facing copy is stable keys + English defaults.
|
|
25
|
+
|
|
26
|
+
## Install (consuming app)
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
npm install @chipmobilesdk/rn-auth react-native-app-auth react-native-keychain
|
|
30
|
+
cd ios && pod install
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`react`, `react-native`, `react-native-app-auth`, and `react-native-keychain`
|
|
34
|
+
are **peer dependencies**. The two native libraries are only required by the
|
|
35
|
+
default adapters — an app injecting custom ports may omit them.
|
|
36
|
+
|
|
37
|
+
See [native setup](../../specs/003-mobile-entra-auth/contracts/native-setup.md)
|
|
38
|
+
for the iOS `Info.plist` URL scheme and the Android `appAuthRedirectScheme`
|
|
39
|
+
Gradle placeholder.
|
|
40
|
+
|
|
41
|
+
## Quick start
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import {
|
|
45
|
+
AuthProvider,
|
|
46
|
+
createAuth,
|
|
47
|
+
createAppAuthClient,
|
|
48
|
+
createKeychainSecureStore,
|
|
49
|
+
useAuth,
|
|
50
|
+
useSignInProvider,
|
|
51
|
+
} from '@chipmobilesdk/rn-auth';
|
|
52
|
+
|
|
53
|
+
const auth = createAuth({
|
|
54
|
+
authority: 'https://<tenant>.ciamlogin.com/<tenant>.onmicrosoft.com',
|
|
55
|
+
clientId: '<public-client-id>',
|
|
56
|
+
redirectUrl: 'com.yourapp://oauthredirect',
|
|
57
|
+
scopes: ['openid', 'profile', 'offline_access'],
|
|
58
|
+
providers: [
|
|
59
|
+
{ id: 'google', platforms: ['android'], domainHint: 'google.com', labelKey: 'auth.action.continueGoogle' },
|
|
60
|
+
{ id: 'apple', platforms: ['ios'], domainHint: 'apple.com', labelKey: 'auth.action.continueApple' },
|
|
61
|
+
// Optional third provider, shown on both platforms after the platform-native one:
|
|
62
|
+
{ id: 'facebook', platforms: ['ios', 'android'], domainHint: 'facebook.com', labelKey: 'auth.action.continueFacebook' },
|
|
63
|
+
],
|
|
64
|
+
resources: [{ key: 'storage', scopes: ['https://storage.azure.com/user_impersonation'] }],
|
|
65
|
+
accessTierMapping: { premiumGroupObjectIds: ['<premium-group-object-id>'] },
|
|
66
|
+
secureStore: createKeychainSecureStore(),
|
|
67
|
+
authClient: createAppAuthClient(),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
export const App = () => (
|
|
71
|
+
<AuthProvider auth={auth}>
|
|
72
|
+
<Screen />
|
|
73
|
+
</AuthProvider>
|
|
74
|
+
);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Hooks: `useAuth()` (state + `signIn`/`signOut`/`signOutGlobal`/`restore`/`requirePremium`),
|
|
78
|
+
`useProfile()`, `useAccessTier()`, `useAccessToken(resourceKey)`,
|
|
79
|
+
`useSignInProviders()` (all platform providers, in config order — map to one
|
|
80
|
+
button each) and `useSignInProvider()` (first available, for a single-button UI).
|
|
81
|
+
|
|
82
|
+
### Session lifecycle guarantees
|
|
83
|
+
|
|
84
|
+
- **Restore deletes the stored session only when the provider rejects the refresh
|
|
85
|
+
token** (`invalid_grant` and the equivalent AADSTS codes). A timeout, a 5xx or an
|
|
86
|
+
error the package cannot classify restores `offline`: cached profile, tier
|
|
87
|
+
unverified, retried on the next `restore()`.
|
|
88
|
+
- **A sign-out wins.** A token refresh still in flight when the user signs out is
|
|
89
|
+
discarded; it cannot write a token back or return the state to `authenticated`.
|
|
90
|
+
- **Rotated refresh tokens are persisted** as soon as they arrive, and concurrent
|
|
91
|
+
`requestAccessToken` calls for one resource share one network refresh.
|
|
92
|
+
- **`signOutGlobal()` returns `{ global: 'ended' | 'failed', error? }`.** Local state
|
|
93
|
+
is cleared either way; `failed` means the tenant session may still be alive.
|
|
94
|
+
|
|
95
|
+
## Configuration contract (LIB-010)
|
|
96
|
+
|
|
97
|
+
The library accepts **public values only**. Provider secrets, Apple keys, and
|
|
98
|
+
client secrets are configured in the External ID tenant, never in the app
|
|
99
|
+
([FR-017](../../specs/003-mobile-entra-auth/spec.md)).
|
|
100
|
+
|
|
101
|
+
| Section | Keys |
|
|
102
|
+
|---------|------|
|
|
103
|
+
| A — Tenant / client | `authority`, `clientId`, `redirectUrl`, `scopes` (include `offline_access`) |
|
|
104
|
+
| B — Android Google | `providers[google]`: `domainHint`, `platforms: ['android']`, `labelKey` |
|
|
105
|
+
| C — iOS Apple | `providers[apple]`: `domainHint`, `platforms: ['ios']`, `labelKey` |
|
|
106
|
+
| C2 — Facebook (optional) | `providers[facebook]`: `domainHint: 'facebook.com'`, `platforms: ['ios','android']`, `labelKey: 'auth.action.continueFacebook'`, optional `available` |
|
|
107
|
+
| D — Resources | `resources[].key`, `resources[].scopes`, `resources[].displayName?` |
|
|
108
|
+
| E — Access tier | `accessTierMapping.premiumGroupObjectIds` (+ optional role names / claim matchers; display names are diagnostics-only) |
|
|
109
|
+
| F — Ports | `secureStore` (required), `authClient` (optional), `messages` (optional copy override) |
|
|
110
|
+
|
|
111
|
+
Full contract: [auth-config.md](../../specs/003-mobile-entra-auth/contracts/auth-config.md)
|
|
112
|
+
and [public-api.md](../../specs/003-mobile-entra-auth/contracts/public-api.md).
|
|
113
|
+
|
|
114
|
+
## Tenant / provider prerequisite checklist (LIB-018)
|
|
115
|
+
|
|
116
|
+
These are **external** prerequisites (FR-013/FR-018) completed before the library
|
|
117
|
+
can sign users in:
|
|
118
|
+
|
|
119
|
+
**External ID tenant**
|
|
120
|
+
- [ ] Customer (CIAM) tenant created; sign-up/sign-in user flow configured.
|
|
121
|
+
- [ ] App registration created as a **public client**; redirect URI added (must match the native scheme, e.g. `com.yourapp://oauthredirect`).
|
|
122
|
+
- [ ] API permissions / scopes for each target Azure resource consented.
|
|
123
|
+
- [ ] Premium group(s) created; record the **group object id** (not the name).
|
|
124
|
+
- [ ] Groups (or roles) emitted in the token; plan for groups overage.
|
|
125
|
+
|
|
126
|
+
**Google (federated in the tenant)**
|
|
127
|
+
- [ ] Google Cloud OAuth client configured; client id/secret stored in the **tenant** IdP config (never in the app).
|
|
128
|
+
- [ ] Google added as an identity provider in the External ID user flow.
|
|
129
|
+
|
|
130
|
+
**Apple (federated in the tenant)**
|
|
131
|
+
- [ ] Apple Services ID + Sign in with Apple key configured; stored in the **tenant** IdP config.
|
|
132
|
+
- [ ] Apple added as an identity provider in the External ID user flow.
|
|
133
|
+
- [ ] Note: Apple sign-in operational credentials expire on a schedule and must be rotated tenant-side.
|
|
134
|
+
|
|
135
|
+
**Facebook (federated in the tenant — optional)**
|
|
136
|
+
- [ ] Facebook app created in Meta for Developers; **App ID + App Secret** stored in the **tenant** IdP config (never in the app).
|
|
137
|
+
- [ ] Facebook added as an identity provider in the External ID user flow; `domain_hint` confirmed (expected `facebook.com`).
|
|
138
|
+
- [ ] Facebook app OAuth redirect / valid OAuth domains match the tenant federation redirect.
|
|
139
|
+
- [ ] iOS: because Facebook is a third-party login, keep Sign in with Apple offered on iOS (Apple guideline 4.8).
|
|
140
|
+
- [ ] Update Apple App Privacy and Google Play Data Safety to include Facebook as an identity provider before release.
|
|
141
|
+
|
|
142
|
+
## Security & privacy
|
|
143
|
+
|
|
144
|
+
- Tokens and refresh artifacts persist only in `SecureTokenStore` (Keychain /
|
|
145
|
+
Keystore). Access tokens are kept in memory only.
|
|
146
|
+
- Access-tier decisions prefer stable group **object ids**; display names never
|
|
147
|
+
grant access; missing/overage claims fail closed.
|
|
148
|
+
- Diagnostics (`AuthError`) never contain secrets or token values. `AuthError` extends
|
|
149
|
+
`SdkError` from `@chipmobilesdk/rn-core`: `isSdkError(error)` recognises it, `error.pkg`
|
|
150
|
+
is `rn-auth`, and `error.retryable` is true only for `network-unavailable`.
|
|
151
|
+
- Authentication and profile data are collected and transmitted to the
|
|
152
|
+
identity providers and configured Azure resources — update Apple App Privacy
|
|
153
|
+
and Google Play Data Safety before release.
|
|
154
|
+
|
|
155
|
+
## Public API
|
|
156
|
+
|
|
157
|
+
Everything below is exported from `@chipmobilesdk/rn-auth`; deep imports into
|
|
158
|
+
`config/`, `core/`, `tokens/`, `oidc/`, `access/`, `diagnostics/`, or `react/`
|
|
159
|
+
are unsupported.
|
|
160
|
+
|
|
161
|
+
- Controller and configuration: `createAuth`, `Auth`, `AuthConfig`,
|
|
162
|
+
`CreateAuthOptions`, `AuthState`, `AuthStatus`, `RestoreStatus`
|
|
163
|
+
- Identity and access: `Profile`, `ProviderConfig`, `ProviderIdentity`,
|
|
164
|
+
`ResourceConfig`, `AccessTier`, `AccessTierMapping`, `AccessTokenResult`,
|
|
165
|
+
`PremiumGateResult`, `evaluateAccessTier`, `failClosedTier`
|
|
166
|
+
- Ports and default adapters: `SecureTokenStore`, `createKeychainSecureStore`,
|
|
167
|
+
`AUTH_STORAGE_KEY`, `OidcAuthClient`, `createAppAuthClient` and the public OIDC
|
|
168
|
+
request/token types. The two default adapters also have their own entrypoints,
|
|
169
|
+
`@chipmobilesdk/rn-auth/app-auth` and `@chipmobilesdk/rn-auth/keychain`, so an app
|
|
170
|
+
that injects its own client or store can skip them. Neither loads its native
|
|
171
|
+
module until it is used: react-native-app-auth on the first sign-in, refresh or
|
|
172
|
+
sign-out, react-native-keychain on the first read or write. Creating `auth` at
|
|
173
|
+
startup loads neither. A missing module is an `AuthConfigError` at that moment.
|
|
174
|
+
- React: `AuthProvider`, `useAuth`, `useProfile`, `useAccessTier`,
|
|
175
|
+
`useAccessToken`, `useSignInProvider`, `useSignInProviders`, `useAuthSelector`.
|
|
176
|
+
Each hook reads the state through `useSyncExternalStore` and re-renders only when
|
|
177
|
+
what it returns changes: `useProfile` does not render for a status change. Use
|
|
178
|
+
`useAuthSelector(state => …, isEqual?)` for any other slice. `auth.getState()`
|
|
179
|
+
returns the same frozen object until the state changes.
|
|
180
|
+
- Diagnostics and copy: `AuthError`, `AuthConfigError`, `isAuthError`, `redact`,
|
|
181
|
+
`DEFAULT_MESSAGES`, `resolveMessages` and their public code/message types, and
|
|
182
|
+
`authMessages`, the catalog split into `user` and `developer` copy. Register the user
|
|
183
|
+
copy with rn-i18n in one line: `runtimeEntriesFromCatalog(authMessages.user)`.
|
|
184
|
+
|
|
185
|
+
## Testing
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
import { createAuth } from '@chipmobilesdk/rn-auth';
|
|
189
|
+
import { createMemorySecureStore } from '@chipmobilesdk/rn-auth/testing';
|
|
190
|
+
|
|
191
|
+
const auth = createAuth({ ...config, secureStore: createMemorySecureStore(), authClient });
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
`@chipmobilesdk/rn-auth/testing` is a separate entrypoint, so nothing in it reaches a
|
|
195
|
+
production bundle. Besides `createMemorySecureStore(seed?)` it holds the checks every
|
|
196
|
+
adapter must pass: `runSecureTokenStoreConformance` (null for an unknown key, last write
|
|
197
|
+
wins, keys kept apart, safe removal, a long non-ASCII artifact intact) and
|
|
198
|
+
`runOidcAuthClientConformance` (sign-in with claims and a future expiry, refresh, a
|
|
199
|
+
closed sheet as `provider-cancelled`, a rejected refresh token as `session-expired`, and
|
|
200
|
+
sign-out). The package runs them against its doubles and the keychain and app-auth
|
|
201
|
+
adapters; run them against a store or client you inject.
|
|
202
|
+
|
|
203
|
+
## Compatibility and validation
|
|
204
|
+
|
|
205
|
+
React ≥19 · React Native ≥0.85 · `react-native-app-auth` ≥8 ·
|
|
206
|
+
`react-native-keychain` ≥10 · iOS + Android · Node ≥22.11 for tooling.
|
|
207
|
+
|
|
208
|
+
The demo integration lives in `src/screens/AuthDemoScreen.tsx`. Run from the
|
|
209
|
+
repository root:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
npm run typecheck --workspace @chipmobilesdk/rn-auth
|
|
213
|
+
npm run pack:check --workspace @chipmobilesdk/rn-auth
|
|
214
|
+
npm run validate
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Distribution and license
|
|
218
|
+
|
|
219
|
+
Published as a public npm package (`publishConfig.access: public`) for use by
|
|
220
|
+
the owner's applications. License: `UNLICENSED`; no open-source license is
|
|
221
|
+
granted.
|
package/package.json
CHANGED
|
@@ -1,54 +1,72 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@chipmobilesdk/rn-auth",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"private": false,
|
|
5
|
-
"license": "UNLICENSED",
|
|
6
|
-
"main": "src/index.ts",
|
|
7
|
-
"types": "src/index.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"types": "./src/index.ts",
|
|
11
|
-
"react-native": "./src/index.ts",
|
|
12
|
-
"default": "./src/index.ts"
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"react
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
"
|
|
53
|
-
}
|
|
54
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@chipmobilesdk/rn-auth",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"main": "src/index.ts",
|
|
7
|
+
"types": "src/index.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./src/index.ts",
|
|
11
|
+
"react-native": "./src/index.ts",
|
|
12
|
+
"default": "./src/index.ts"
|
|
13
|
+
},
|
|
14
|
+
"./app-auth": {
|
|
15
|
+
"types": "./src/app-auth.ts",
|
|
16
|
+
"react-native": "./src/app-auth.ts",
|
|
17
|
+
"default": "./src/app-auth.ts"
|
|
18
|
+
},
|
|
19
|
+
"./keychain": {
|
|
20
|
+
"types": "./src/keychain.ts",
|
|
21
|
+
"react-native": "./src/keychain.ts",
|
|
22
|
+
"default": "./src/keychain.ts"
|
|
23
|
+
},
|
|
24
|
+
"./testing": {
|
|
25
|
+
"types": "./src/testing/index.ts",
|
|
26
|
+
"react-native": "./src/testing/index.ts",
|
|
27
|
+
"default": "./src/testing/index.ts"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"src/index.ts",
|
|
32
|
+
"src/app-auth.ts",
|
|
33
|
+
"src/keychain.ts",
|
|
34
|
+
"src/config",
|
|
35
|
+
"src/core",
|
|
36
|
+
"src/tokens",
|
|
37
|
+
"src/oidc",
|
|
38
|
+
"src/access",
|
|
39
|
+
"src/diagnostics",
|
|
40
|
+
"src/react",
|
|
41
|
+
"src/testing",
|
|
42
|
+
"skills",
|
|
43
|
+
"README.md",
|
|
44
|
+
"CHANGELOG.md"
|
|
45
|
+
],
|
|
46
|
+
"sideEffects": false,
|
|
47
|
+
"scripts": {
|
|
48
|
+
"typecheck": "tsc -p tsconfig.json && tsc -p tsconfig.test.json",
|
|
49
|
+
"pack:check": "npm pack --dry-run"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@chipmobilesdk/rn-core": "^0.1.0"
|
|
53
|
+
},
|
|
54
|
+
"peerDependencies": {
|
|
55
|
+
"react": ">=19",
|
|
56
|
+
"react-native": ">=0.85",
|
|
57
|
+
"react-native-app-auth": ">=8",
|
|
58
|
+
"react-native-keychain": ">=10"
|
|
59
|
+
},
|
|
60
|
+
"peerDependenciesMeta": {
|
|
61
|
+
"react-native-app-auth": {
|
|
62
|
+
"optional": true
|
|
63
|
+
},
|
|
64
|
+
"react-native-keychain": {
|
|
65
|
+
"optional": true
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"publishConfig": {
|
|
69
|
+
"access": "public",
|
|
70
|
+
"registry": "https://registry.npmjs.org/"
|
|
71
|
+
}
|
|
72
|
+
}
|