@gh-platform/auth-sdk 1.0.12 → 1.0.14
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/dist/auth-sdk.es.js +7 -26
- package/dist/auth-sdk.min.js +1 -1
- package/dist/auth-sdk.umd.js +1 -1
- package/dist/index.d.ts +2 -0
- package/package.json +2 -2
- package/src/index.d.ts +2 -0
- package/src/middleware.js +7 -51
package/dist/auth-sdk.es.js
CHANGED
|
@@ -147,12 +147,10 @@ class AuthFetch {
|
|
|
147
147
|
this.introspectUrl = `${introspectBaseUrl}/${introspectPath.replace(/^\//, "")}`;
|
|
148
148
|
this.storage = storage || new TokenStorage("auth", authClient.tenant || null);
|
|
149
149
|
}
|
|
150
|
-
|
|
151
|
-
const maxAge = 60 * 5;
|
|
150
|
+
setAuthCookie() {
|
|
152
151
|
const parts = [
|
|
153
152
|
`auth_state=1`,
|
|
154
153
|
`Path=/`,
|
|
155
|
-
`Max-Age=${maxAge}`,
|
|
156
154
|
`SameSite=Lax`
|
|
157
155
|
];
|
|
158
156
|
if (location.protocol === "https:") {
|
|
@@ -160,7 +158,7 @@ class AuthFetch {
|
|
|
160
158
|
}
|
|
161
159
|
document.cookie = parts.join("; ");
|
|
162
160
|
}
|
|
163
|
-
|
|
161
|
+
clearAuthCookie() {
|
|
164
162
|
document.cookie = `auth_state=; Path=/; Max-Age=0`;
|
|
165
163
|
}
|
|
166
164
|
/**
|
|
@@ -244,27 +242,14 @@ class AuthFetch {
|
|
|
244
242
|
finalToken = this.storage.accessToken;
|
|
245
243
|
}
|
|
246
244
|
if (!finalToken) {
|
|
247
|
-
this._clearAuthCookie();
|
|
248
245
|
throw new Error("No access token available for introspection");
|
|
249
246
|
}
|
|
250
247
|
if (!this.introspectUrl) {
|
|
251
248
|
throw new Error("No introspect url config");
|
|
252
249
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
method: "GET"
|
|
257
|
-
});
|
|
258
|
-
} catch (err) {
|
|
259
|
-
throw err;
|
|
260
|
-
}
|
|
261
|
-
if (res.status === 401 || res.status === 403) {
|
|
262
|
-
this._clearAuthCookie();
|
|
263
|
-
throw new Error(`Unauthorized: ${res.status}`);
|
|
264
|
-
}
|
|
265
|
-
if (res.status >= 500) {
|
|
266
|
-
throw new Error(`Auth service error: ${res.status}`);
|
|
267
|
-
}
|
|
250
|
+
const res = await this.fetch(this.introspectUrl, {
|
|
251
|
+
method: "GET"
|
|
252
|
+
});
|
|
268
253
|
if (!res.ok) {
|
|
269
254
|
const text = await res.text().catch(() => res.statusText);
|
|
270
255
|
throw new Error(`Introspect failed: ${res.status} ${text}`);
|
|
@@ -273,13 +258,9 @@ class AuthFetch {
|
|
|
273
258
|
try {
|
|
274
259
|
json = await res.json();
|
|
275
260
|
} catch (e) {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
if (json.active === false) {
|
|
279
|
-
this._clearAuthCookie();
|
|
280
|
-
throw new Error("Token inactive");
|
|
261
|
+
console.error("❌ JSON parse error:", e);
|
|
262
|
+
throw new Error("Invalid JSON response from server");
|
|
281
263
|
}
|
|
282
|
-
this._setAuthCookie();
|
|
283
264
|
return json;
|
|
284
265
|
}
|
|
285
266
|
}
|
package/dist/auth-sdk.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).AuthSDK={})}(this,function(e){"use strict";let t=null;function r(){return t}function s(e){t=e}class o{constructor({baseUrl:e,tenant:t=null,loginPath:r=null,refreshPath:s=null,headers:o={},storage:
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).AuthSDK={})}(this,function(e){"use strict";let t=null;function r(){return t}function s(e){t=e}class o{constructor({baseUrl:e,tenant:t=null,loginPath:r=null,refreshPath:s=null,headers:o={},storage:n=null}){if(!e)throw new Error("baseUrl is required");this.baseUrl=e.replace(/\/$/,"");const a=t?`/api/v1/${t}/auth`:"/api/v1/auth";this.loginUrl=this.baseUrl+(r||`${a}/login`),this.refreshUrl=this.baseUrl+(s||`${a}/refresh`),this.tenant=t,this.headers={"Content-Type":"application/json",...o},this.storage=n}async login(e,t,r=null,s={}){const o={identifier:e,password:t,...s};r&&(o.totp=r);const n=await fetch(this.loginUrl,{method:"POST",headers:this.headers,body:JSON.stringify(o)});if(!n.ok){const e=await n.text().catch(()=>n.statusText);throw new Error(`Login failed: ${n.status} ${e}`)}let a;try{a=await n.json()}catch(e){throw console.error("❌ JSON parse error:",e),new Error("Invalid JSON response from server")}const i=a.data||a;return this.storage&&(i.access_token&&(this.storage.accessToken=i.access_token),i.refresh_token&&(this.storage.refreshToken=i.refresh_token)),a}async refresh(e){if(r())return r();const t=(async()=>{const t=await fetch(this.refreshUrl,{method:"POST",headers:this.headers,body:JSON.stringify({refresh_token:e})});if(!t.ok){const e=await t.text().catch(()=>t.statusText);throw new Error(`Refresh failed: ${t.status} ${e}`)}let r;try{r=await t.json()}catch(e){throw console.error("❌ JSON parse error:",e),new Error("Invalid JSON response from server")}const s=r.data||r;return this.storage&&(s.access_token&&(this.storage.accessToken=s.access_token),s.refresh_token&&(this.storage.refreshToken=s.refresh_token)),r})();s(t);try{return await t}finally{s(null)}}}class n{constructor(e="auth",t=null){this.prefix=e,this.tenant=t}_key(e){return this.tenant?`${this.prefix}:${this.tenant}_${e}`:`${this.prefix}_${e}`}get accessToken(){return localStorage.getItem(this._key("access_token"))}set accessToken(e){null==e?localStorage.removeItem(this._key("access_token")):localStorage.setItem(this._key("access_token"),e)}get refreshToken(){return localStorage.getItem(this._key("refresh_token"))}set refreshToken(e){null==e?localStorage.removeItem(this._key("refresh_token")):localStorage.setItem(this._key("refresh_token"),e)}clear(){localStorage.removeItem(this._key("access_token")),localStorage.removeItem(this._key("refresh_token"))}}class a{constructor(e,t,r=null,s="introspect"){if(!t)throw new Error("introspectBaseUrl is required");this.client=e,this.introspectUrl=`${t}/${s.replace(/^\//,"")}`,this.storage=r||new n("auth",e.tenant||null)}setAuthCookie(){const e=["auth_state=1","Path=/","SameSite=Lax"];"https:"===location.protocol&&e.push("Secure"),document.cookie=e.join("; ")}clearAuthCookie(){document.cookie="auth_state=; Path=/; Max-Age=0"}async fetch(e,t={},r=null){const s=this.storage.accessToken,o=new Headers(t.headers||{});return s&&o.set("Authorization",`Bearer ${s}`),t.method&&"GET"!==t.method&&t.body?await this._xhrRequest(e,t,o,r):await this._fetchWithDownloadProgress(e,t,o,r)}async _fetchWithDownloadProgress(e,t,r,s){let o=await fetch(e,{...t,headers:r});if(401===o.status&&this.storage.refreshToken)try{const s=await this.client.refresh(this.storage.refreshToken);s.access_token&&(this.storage.accessToken=s.access_token),s.refresh_token&&(this.storage.refreshToken=s.refresh_token),r.set("Authorization",`Bearer ${this.storage.accessToken}`),o=await fetch(e,{...t,headers:r})}catch{throw this.storage.clear(),new Error("Unauthorized, please login again")}if(!s||!o.body)return o;const n=o.body.getReader(),a=+o.headers.get("Content-Length")||0;let i=0;const h=[];for(;;){const{done:e,value:t}=await n.read();if(e)break;h.push(t),i+=t.length,a?s(Math.round(i/a*100),i,a):s(null,i,null)}const c=new Blob(h);return new Response(c,o)}_xhrRequest(e,t,r,s){return new Promise((o,n)=>{const a=new XMLHttpRequest;a.open(t.method||"POST",e,!0);for(const[e,t]of r.entries())a.setRequestHeader(e,t);a.upload&&s&&(a.upload.onprogress=e=>{if(e.lengthComputable){const t=Math.round(e.loaded/e.total*100);s(t,e.loaded,e.total)}else s(null,e.loaded,null)}),a.onload=()=>{o(new Response(a.response,{status:a.status}))},a.onerror=()=>n(new Error("Network error")),a.send(t.body)})}async introspect(e=null){let t=e;if(this.storage&&!t&&(t=this.storage.accessToken),!t)throw new Error("No access token available for introspection");if(!this.introspectUrl)throw new Error("No introspect url config");const r=await this.fetch(this.introspectUrl,{method:"GET"});if(!r.ok){const e=await r.text().catch(()=>r.statusText);throw new Error(`Introspect failed: ${r.status} ${e}`)}let s;try{s=await r.json()}catch(e){throw console.error("❌ JSON parse error:",e),new Error("Invalid JSON response from server")}return s}}const i={AuthClient:o,AuthFetch:a,TokenStorage:n};e.AuthClient=o,e.AuthFetch=a,e.TokenStorage=n,e.default=i,Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
package/dist/auth-sdk.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).AuthSDK={})}(this,function(e){"use strict";let t=null;function r(){return t}function s(e){t=e}class o{constructor({baseUrl:e,tenant:t=null,loginPath:r=null,refreshPath:s=null,headers:o={},storage:
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).AuthSDK={})}(this,function(e){"use strict";let t=null;function r(){return t}function s(e){t=e}class o{constructor({baseUrl:e,tenant:t=null,loginPath:r=null,refreshPath:s=null,headers:o={},storage:n=null}){if(!e)throw new Error("baseUrl is required");this.baseUrl=e.replace(/\/$/,"");const a=t?`/api/v1/${t}/auth`:"/api/v1/auth";this.loginUrl=this.baseUrl+(r||`${a}/login`),this.refreshUrl=this.baseUrl+(s||`${a}/refresh`),this.tenant=t,this.headers={"Content-Type":"application/json",...o},this.storage=n}async login(e,t,r=null,s={}){const o={identifier:e,password:t,...s};r&&(o.totp=r);const n=await fetch(this.loginUrl,{method:"POST",headers:this.headers,body:JSON.stringify(o)});if(!n.ok){const e=await n.text().catch(()=>n.statusText);throw new Error(`Login failed: ${n.status} ${e}`)}let a;try{a=await n.json()}catch(h){throw console.error("❌ JSON parse error:",h),new Error("Invalid JSON response from server")}const i=a.data||a;return this.storage&&(i.access_token&&(this.storage.accessToken=i.access_token),i.refresh_token&&(this.storage.refreshToken=i.refresh_token)),a}async refresh(e){if(r())return r();const t=(async()=>{const t=await fetch(this.refreshUrl,{method:"POST",headers:this.headers,body:JSON.stringify({refresh_token:e})});if(!t.ok){const e=await t.text().catch(()=>t.statusText);throw new Error(`Refresh failed: ${t.status} ${e}`)}let r;try{r=await t.json()}catch(o){throw console.error("❌ JSON parse error:",o),new Error("Invalid JSON response from server")}const s=r.data||r;return this.storage&&(s.access_token&&(this.storage.accessToken=s.access_token),s.refresh_token&&(this.storage.refreshToken=s.refresh_token)),r})();s(t);try{return await t}finally{s(null)}}}class n{constructor(e="auth",t=null){this.prefix=e,this.tenant=t}_key(e){return this.tenant?`${this.prefix}:${this.tenant}_${e}`:`${this.prefix}_${e}`}get accessToken(){return localStorage.getItem(this._key("access_token"))}set accessToken(e){null==e?localStorage.removeItem(this._key("access_token")):localStorage.setItem(this._key("access_token"),e)}get refreshToken(){return localStorage.getItem(this._key("refresh_token"))}set refreshToken(e){null==e?localStorage.removeItem(this._key("refresh_token")):localStorage.setItem(this._key("refresh_token"),e)}clear(){localStorage.removeItem(this._key("access_token")),localStorage.removeItem(this._key("refresh_token"))}}class a{constructor(e,t,r=null,s="introspect"){if(!t)throw new Error("introspectBaseUrl is required");this.client=e,this.introspectUrl=`${t}/${s.replace(/^\//,"")}`,this.storage=r||new n("auth",e.tenant||null)}setAuthCookie(){const e=["auth_state=1","Path=/","SameSite=Lax"];"https:"===location.protocol&&e.push("Secure"),document.cookie=e.join("; ")}clearAuthCookie(){document.cookie="auth_state=; Path=/; Max-Age=0"}async fetch(e,t={},r=null){const s=this.storage.accessToken,o=new Headers(t.headers||{});return s&&o.set("Authorization",`Bearer ${s}`),t.method&&"GET"!==t.method&&t.body?await this._xhrRequest(e,t,o,r):await this._fetchWithDownloadProgress(e,t,o,r)}async _fetchWithDownloadProgress(e,t,r,s){let o=await fetch(e,{...t,headers:r});if(401===o.status&&this.storage.refreshToken)try{const s=await this.client.refresh(this.storage.refreshToken);s.access_token&&(this.storage.accessToken=s.access_token),s.refresh_token&&(this.storage.refreshToken=s.refresh_token),r.set("Authorization",`Bearer ${this.storage.accessToken}`),o=await fetch(e,{...t,headers:r})}catch{throw this.storage.clear(),new Error("Unauthorized, please login again")}if(!s||!o.body)return o;const n=o.body.getReader(),a=+o.headers.get("Content-Length")||0;let i=0;const h=[];for(;;){const{done:e,value:t}=await n.read();if(e)break;if(h.push(t),i+=t.length,a){s(Math.round(i/a*100),i,a)}else s(null,i,null)}const c=new Blob(h);return new Response(c,o)}_xhrRequest(e,t,r,s){return new Promise((o,n)=>{const a=new XMLHttpRequest;a.open(t.method||"POST",e,!0);for(const[e,t]of r.entries())a.setRequestHeader(e,t);a.upload&&s&&(a.upload.onprogress=e=>{if(e.lengthComputable){const t=Math.round(e.loaded/e.total*100);s(t,e.loaded,e.total)}else s(null,e.loaded,null)}),a.onload=()=>{o(new Response(a.response,{status:a.status}))},a.onerror=()=>n(new Error("Network error")),a.send(t.body)})}async introspect(e=null){let t=e;if(this.storage&&!t&&(t=this.storage.accessToken),!t)throw new Error("No access token available for introspection");if(!this.introspectUrl)throw new Error("No introspect url config");const r=await this.fetch(this.introspectUrl,{method:"GET"});if(!r.ok){const e=await r.text().catch(()=>r.statusText);throw new Error(`Introspect failed: ${r.status} ${e}`)}let s;try{s=await r.json()}catch(o){throw console.error("❌ JSON parse error:",o),new Error("Invalid JSON response from server")}return s}}const i={AuthClient:o,AuthFetch:a,TokenStorage:n};e.AuthClient=o,e.AuthFetch=a,e.TokenStorage=n,e.default=i,Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
package/dist/index.d.ts
CHANGED
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
package/src/middleware.js
CHANGED
|
@@ -10,14 +10,10 @@ export class AuthFetch {
|
|
|
10
10
|
this.introspectUrl = (`${introspectBaseUrl}/${introspectPath.replace(/^\//, "")}`);
|
|
11
11
|
this.storage = storage || new TokenStorage("auth", authClient.tenant || null);
|
|
12
12
|
}
|
|
13
|
-
|
|
14
|
-
_setAuthCookie() {
|
|
15
|
-
const maxAge = 60 * 5; // 5 phút
|
|
16
|
-
|
|
13
|
+
setAuthCookie() {
|
|
17
14
|
const parts = [
|
|
18
15
|
`auth_state=1`,
|
|
19
16
|
`Path=/`,
|
|
20
|
-
`Max-Age=${maxAge}`,
|
|
21
17
|
`SameSite=Lax`,
|
|
22
18
|
];
|
|
23
19
|
|
|
@@ -28,8 +24,7 @@ export class AuthFetch {
|
|
|
28
24
|
document.cookie = parts.join("; ");
|
|
29
25
|
}
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
_clearAuthCookie() {
|
|
27
|
+
clearAuthCookie() {
|
|
33
28
|
document.cookie = `auth_state=; Path=/; Max-Age=0`;
|
|
34
29
|
}
|
|
35
30
|
|
|
@@ -141,44 +136,18 @@ export class AuthFetch {
|
|
|
141
136
|
finalToken = this.storage.accessToken;
|
|
142
137
|
}
|
|
143
138
|
|
|
144
|
-
// ❌ không có token => chắc chắn chưa login
|
|
145
139
|
if (!finalToken) {
|
|
146
|
-
this._clearAuthCookie();
|
|
147
140
|
throw new Error("No access token available for introspection");
|
|
148
141
|
}
|
|
149
|
-
|
|
150
142
|
if (!this.introspectUrl) {
|
|
151
143
|
throw new Error("No introspect url config");
|
|
152
144
|
}
|
|
153
145
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
method: "GET",
|
|
158
|
-
});
|
|
159
|
-
} catch (err) {
|
|
160
|
-
// ⚠️ NETWORK / FETCH ERROR
|
|
161
|
-
// KHÔNG clear cookie
|
|
162
|
-
throw err;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// ===============================
|
|
166
|
-
// AUTH INVALID → CLEAR COOKIE
|
|
167
|
-
// ===============================
|
|
168
|
-
if (res.status === 401 || res.status === 403) {
|
|
169
|
-
this._clearAuthCookie();
|
|
170
|
-
throw new Error(`Unauthorized: ${res.status}`);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// ===============================
|
|
174
|
-
// SERVER ERROR → KEEP COOKIE
|
|
175
|
-
// ===============================
|
|
176
|
-
if (res.status >= 500) {
|
|
177
|
-
throw new Error(`Auth service error: ${res.status}`);
|
|
178
|
-
}
|
|
146
|
+
const res = await this.fetch(this.introspectUrl, {
|
|
147
|
+
method: "GET",
|
|
148
|
+
});
|
|
179
149
|
|
|
180
150
|
if (!res.ok) {
|
|
181
|
-
// các status khác (400, 404...) → không clear
|
|
182
151
|
const text = await res.text().catch(() => res.statusText);
|
|
183
152
|
throw new Error(`Introspect failed: ${res.status} ${text}`);
|
|
184
153
|
}
|
|
@@ -187,23 +156,10 @@ export class AuthFetch {
|
|
|
187
156
|
try {
|
|
188
157
|
json = await res.json();
|
|
189
158
|
} catch (e) {
|
|
190
|
-
|
|
191
|
-
throw new Error("Invalid JSON response from
|
|
159
|
+
console.error("❌ JSON parse error:", e);
|
|
160
|
+
throw new Error("Invalid JSON response from server");
|
|
192
161
|
}
|
|
193
162
|
|
|
194
|
-
// ===============================
|
|
195
|
-
// AUTH SERVICE NÓI TOKEN INVALID
|
|
196
|
-
// ===============================
|
|
197
|
-
if (json.active === false) {
|
|
198
|
-
this._clearAuthCookie();
|
|
199
|
-
throw new Error("Token inactive");
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// ===============================
|
|
203
|
-
// AUTH OK → SET COOKIE
|
|
204
|
-
// ===============================
|
|
205
|
-
this._setAuthCookie();
|
|
206
|
-
|
|
207
163
|
return json;
|
|
208
164
|
}
|
|
209
165
|
}
|