authkit-react-native 0.1.2 → 0.1.3

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 (2) hide show
  1. package/dist/index.js +100 -70
  2. package/package.json +6 -6
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  makeRedirectUri,
6
6
  RefreshTokenRequest,
7
7
  RevokeTokenRequest,
8
+ TokenError,
8
9
  TokenResponse
9
10
  } from "expo-auth-session";
10
11
  import * as WebBrowser from "expo-web-browser";
@@ -86,85 +87,114 @@ function createAuthStore(config) {
86
87
  ]);
87
88
  return meta;
88
89
  }
89
- const store = createStore()((set) => ({
90
- isLoading: true,
91
- signIn: async ({ screenHint = "sign-in" } = {}) => {
92
- const authSessionRequest = new AuthRequest({
93
- clientId,
94
- redirectUri,
95
- extraParams: { provider: "authkit", screen_hint: screenHint }
96
- });
97
- const authSessionResult = await authSessionRequest.promptAsync({
98
- authorizationEndpoint
99
- });
100
- if (authSessionResult.type === "error") {
101
- throw new Error(
102
- authSessionResult.error?.description ?? "Unknown error"
103
- );
90
+ const store = createStore()((set) => {
91
+ let refreshInFlight = null;
92
+ function refreshSession(tokenResponse) {
93
+ if (!refreshInFlight) {
94
+ refreshInFlight = (async () => {
95
+ try {
96
+ const refreshTokenRequest = new RefreshTokenRequest({
97
+ refreshToken: tokenResponse.refreshToken,
98
+ clientId
99
+ });
100
+ const refreshed = await refreshTokenRequest.performAsync({
101
+ tokenEndpoint
102
+ });
103
+ const meta = await storeTokenResponse(refreshed);
104
+ set(meta);
105
+ return refreshed.accessToken;
106
+ } finally {
107
+ refreshInFlight = null;
108
+ }
109
+ })();
104
110
  }
105
- if (authSessionResult.type !== "success") {
106
- return false;
107
- }
108
- if (authSessionRequest.state !== authSessionResult.params.state) {
109
- throw new Error("State mismatch");
110
- }
111
- if (!authSessionRequest.codeVerifier) {
112
- throw new Error("Code verifier missing");
113
- }
114
- const tokenRequest = new AccessTokenRequest({
115
- code: authSessionResult.params.code,
116
- clientId,
117
- redirectUri,
118
- extraParams: {
119
- code_verifier: authSessionRequest.codeVerifier
111
+ return refreshInFlight;
112
+ }
113
+ return {
114
+ isLoading: true,
115
+ signIn: async ({ screenHint = "sign-in" } = {}) => {
116
+ const authSessionRequest = new AuthRequest({
117
+ clientId,
118
+ redirectUri,
119
+ extraParams: { provider: "authkit", screen_hint: screenHint }
120
+ });
121
+ const authSessionResult = await authSessionRequest.promptAsync({
122
+ authorizationEndpoint
123
+ });
124
+ if (authSessionResult.type === "error") {
125
+ throw new Error(
126
+ authSessionResult.error?.description ?? "Unknown error"
127
+ );
120
128
  }
121
- });
122
- const tokenResponse = await tokenRequest.performAsync({ tokenEndpoint });
123
- const meta = await storeTokenResponse(tokenResponse);
124
- set(meta);
125
- return true;
126
- },
127
- signOut: async () => {
128
- const tokenResponse = await readTokenResponse();
129
- if (tokenResponse?.accessToken) {
130
- const revokeTokenRequest = new RevokeTokenRequest({
129
+ if (authSessionResult.type !== "success") {
130
+ return false;
131
+ }
132
+ if (authSessionRequest.state !== authSessionResult.params.state) {
133
+ throw new Error("State mismatch");
134
+ }
135
+ if (!authSessionRequest.codeVerifier) {
136
+ throw new Error("Code verifier missing");
137
+ }
138
+ const tokenRequest = new AccessTokenRequest({
139
+ code: authSessionResult.params.code,
131
140
  clientId,
132
- token: tokenResponse.accessToken
141
+ redirectUri,
142
+ extraParams: {
143
+ code_verifier: authSessionRequest.codeVerifier
144
+ }
133
145
  });
134
- await revokeTokenRequest.performAsync({ revocationEndpoint });
135
- }
136
- await storage.clear();
137
- set(emptySession);
138
- },
139
- getAccessToken: async (options) => {
140
- const forceRefresh = options?.forceRefresh ?? false;
141
- try {
142
- let tokenResponse = await readTokenResponse();
143
- if (!tokenResponse) {
146
+ const tokenResponse = await tokenRequest.performAsync({
147
+ tokenEndpoint
148
+ });
149
+ const meta = await storeTokenResponse(tokenResponse);
150
+ set(meta);
151
+ return true;
152
+ },
153
+ signOut: async () => {
154
+ try {
155
+ const tokenResponse = await readTokenResponse();
156
+ if (tokenResponse?.accessToken) {
157
+ const revokeTokenRequest = new RevokeTokenRequest({
158
+ clientId,
159
+ token: tokenResponse.accessToken
160
+ });
161
+ await revokeTokenRequest.performAsync({ revocationEndpoint });
162
+ }
163
+ } catch (error) {
164
+ if (devMode) console.error(error);
165
+ } finally {
144
166
  await storage.clear();
145
167
  set(emptySession);
146
- return null;
147
168
  }
148
- if (forceRefresh || tokenResponse.shouldRefresh()) {
149
- const refreshTokenRequest = new RefreshTokenRequest({
150
- refreshToken: tokenResponse.refreshToken,
151
- clientId
152
- });
153
- tokenResponse = await refreshTokenRequest.performAsync({
154
- tokenEndpoint
155
- });
156
- const meta = await storeTokenResponse(tokenResponse);
157
- set(meta);
169
+ },
170
+ getAccessToken: async (options) => {
171
+ const forceRefresh = options?.forceRefresh ?? false;
172
+ try {
173
+ const tokenResponse = await readTokenResponse();
174
+ if (!tokenResponse) {
175
+ await storage.clear();
176
+ set(emptySession);
177
+ return null;
178
+ }
179
+ if (forceRefresh || tokenResponse.shouldRefresh()) {
180
+ try {
181
+ return await refreshSession(tokenResponse);
182
+ } catch (error) {
183
+ if (error instanceof TokenError) throw error;
184
+ if (devMode) console.error(error);
185
+ return TokenResponse.isTokenFresh(tokenResponse) ? tokenResponse.accessToken : null;
186
+ }
187
+ }
188
+ return tokenResponse.accessToken;
189
+ } catch (error) {
190
+ if (devMode) console.error(error);
191
+ await storage.clear();
192
+ set(emptySession);
193
+ return null;
158
194
  }
159
- return tokenResponse.accessToken;
160
- } catch (error) {
161
- if (devMode) console.error(error);
162
- await storage.clear();
163
- set(emptySession);
164
- return null;
165
195
  }
166
- }
167
- }));
196
+ };
197
+ });
168
198
  (async () => {
169
199
  try {
170
200
  const storedMeta = await storage.readMeta();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "authkit-react-native",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "WorkOS AuthKit integration for React Native — OAuth 2.0 PKCE auth with token storage, session restoration, and automatic refresh",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -56,12 +56,12 @@
56
56
  "devDependencies": {
57
57
  "@changesets/changelog-github": "^0.7.0",
58
58
  "@changesets/cli": "^2.30.0",
59
- "@react-native-async-storage/async-storage": "^2.2.0",
59
+ "@react-native-async-storage/async-storage": "^3.1.1",
60
60
  "@vitest/coverage-v8": "^4.1.0",
61
- "expo-auth-session": "^55.0.7",
62
- "expo-secure-store": "^55.0.8",
63
- "expo-web-browser": "^55.0.9",
64
- "lint-staged": "^16.1.0",
61
+ "expo-auth-session": "^57.0.1",
62
+ "expo-secure-store": "^57.0.0",
63
+ "expo-web-browser": "^57.0.0",
64
+ "lint-staged": "^17.0.8",
65
65
  "prettier": "^3.8.1",
66
66
  "react": "^19.2.0",
67
67
  "simple-git-hooks": "^2.13.0",