@cemiar/auth-sdk 1.0.23 → 1.0.24

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.
@@ -5,11 +5,11 @@ export declare class CemiarAuthClient implements CemiarAuthClientInstance {
5
5
  private readonly tenantId;
6
6
  private readonly auds;
7
7
  private readonly redirectUrl?;
8
- private readonly onAuthFailure?;
9
8
  private storage;
9
+ private readonly onTokenChange?;
10
+ private readonly onAuthFailure?;
10
11
  private loginMethod;
11
- private isRefreshing;
12
- private failedQueue;
12
+ private refreshPromise;
13
13
  constructor(config: CemiarAuthClientConfig);
14
14
  getAccessToken(): string | null;
15
15
  setAccessToken(token: string | null): void;
@@ -23,8 +23,9 @@ export declare class CemiarAuthClient implements CemiarAuthClientInstance {
23
23
  createApiClient(options: CreateApiClientOptions): AxiosInstance;
24
24
  attachInterceptors(instance: AxiosInstance): AxiosInstance;
25
25
  private addAuthHeader;
26
- private processQueue;
27
26
  private handleResponseError;
27
+ private queueTokenRefresh;
28
+ private handleAuthFailure;
28
29
  private loadLoginMethodFromStorage;
29
30
  private persistLoginMethod;
30
31
  private getCurrentLoginMethod;
@@ -17,25 +17,27 @@ export class CemiarAuthClient {
17
17
  constructor(config) {
18
18
  var _a, _b;
19
19
  this.storage = createDefaultTokenStorage();
20
- this.isRefreshing = false;
21
- this.failedQueue = [];
20
+ this.refreshPromise = null;
22
21
  this.baseUrl = normalizeBaseUrl(config.baseUrl || "http://localhost:3000") + "/auth";
23
22
  this.tenantId = config.tenantId;
24
23
  this.auds = parseAuds(config.auds);
25
24
  this.redirectUrl =
26
25
  (_a = config.redirectUrl) !== null && _a !== void 0 ? _a : (isBrowser ? `${window.location.origin}/auth/microsoft/callback` : undefined);
27
- this.storage = (_b = config.storage) !== null && _b !== void 0 ? _b : createDefaultTokenStorage();
26
+ this.onTokenChange = config.onTokenChange;
28
27
  this.onAuthFailure = config.onAuthFailure;
28
+ this.storage = (_b = config.storage) !== null && _b !== void 0 ? _b : createDefaultTokenStorage();
29
29
  this.loginMethod = this.loadLoginMethodFromStorage();
30
30
  }
31
31
  getAccessToken() {
32
32
  return this.storage.getToken();
33
33
  }
34
34
  setAccessToken(token) {
35
+ var _a;
35
36
  this.storage.setToken(token);
36
37
  if (token === null) {
37
38
  this.persistLoginMethod(null);
38
39
  }
40
+ (_a = this.onTokenChange) === null || _a === void 0 ? void 0 : _a.call(this, token);
39
41
  }
40
42
  async authPost(path, body, withCredentials = true) {
41
43
  const url = `${this.baseUrl}${path}`;
@@ -129,55 +131,40 @@ export class CemiarAuthClient {
129
131
  }
130
132
  return config;
131
133
  }
132
- processQueue(error, token = null) {
133
- this.failedQueue.forEach(request => {
134
- if (error) {
135
- request.reject(error);
136
- }
137
- else if (token) {
138
- request.resolve(token);
139
- }
140
- });
141
- this.failedQueue = [];
142
- }
143
134
  async handleResponseError(error, instance) {
144
- var _a, _b;
135
+ var _a;
145
136
  const status = (_a = error.response) === null || _a === void 0 ? void 0 : _a.status;
146
137
  const originalRequest = error.config;
147
138
  if (status !== 401 || !originalRequest || originalRequest._retry) {
148
139
  return Promise.reject(error);
149
140
  }
150
- // If already refreshing, queue this request to wait for the token
151
- if (this.isRefreshing) {
152
- return new Promise((resolve, reject) => {
153
- this.failedQueue.push({ resolve, reject });
154
- }).then(token => {
155
- if (originalRequest.headers) {
156
- originalRequest.headers.Authorization = `Bearer ${token}`;
157
- }
158
- return instance(originalRequest);
159
- });
160
- }
161
141
  originalRequest._retry = true;
162
- this.isRefreshing = true;
163
142
  try {
164
- const { accessToken: newToken } = await this.refreshToken();
165
- this.processQueue(null, newToken);
143
+ const newToken = await this.queueTokenRefresh();
166
144
  if (originalRequest.headers) {
167
145
  originalRequest.headers.Authorization = `Bearer ${newToken}`;
168
146
  }
169
- const response = await instance(originalRequest);
170
- return response;
147
+ return instance(originalRequest);
171
148
  }
172
149
  catch (refreshError) {
173
- this.processQueue(refreshError, null);
174
- this.setAccessToken(null);
175
- (_b = this.onAuthFailure) === null || _b === void 0 ? void 0 : _b.call(this);
150
+ this.handleAuthFailure();
176
151
  return Promise.reject(refreshError);
177
152
  }
178
- finally {
179
- this.isRefreshing = false;
153
+ }
154
+ async queueTokenRefresh() {
155
+ if (!this.refreshPromise) {
156
+ this.refreshPromise = this.refreshToken()
157
+ .then(tokens => tokens.accessToken)
158
+ .finally(() => {
159
+ this.refreshPromise = null;
160
+ });
180
161
  }
162
+ return this.refreshPromise;
163
+ }
164
+ handleAuthFailure() {
165
+ var _a;
166
+ this.setAccessToken(null);
167
+ (_a = this.onAuthFailure) === null || _a === void 0 ? void 0 : _a.call(this);
181
168
  }
182
169
  loadLoginMethodFromStorage() {
183
170
  if (!isBrowser || !("localStorage" in globalThis)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cemiar/auth-sdk",
3
- "version": "1.0.23",
3
+ "version": "1.0.24",
4
4
  "description": "Cemiar Auth integration helpers for web apps and APIs.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",