@bigso/auth-sdk 0.4.7 → 0.5.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/README.md +180 -135
- package/dist/browser/index.cjs +11 -23
- package/dist/browser/index.d.cts +3 -20
- package/dist/browser/index.d.ts +3 -20
- package/dist/browser/index.js +12 -24
- package/dist/chunk-5ECHA2VH.js +32 -0
- package/dist/express/index.cjs +61 -122
- package/dist/express/index.d.cts +16 -13
- package/dist/express/index.d.ts +16 -13
- package/dist/express/index.js +61 -122
- package/dist/node/index.cjs +69 -98
- package/dist/node/index.d.cts +6 -30
- package/dist/node/index.d.ts +6 -30
- package/dist/node/index.js +53 -99
- package/dist/types-BQzACpj3.d.cts +73 -0
- package/dist/types-BQzACpj3.d.ts +73 -0
- package/package.json +2 -2
- package/dist/chunk-LDDK6SJD.js +0 -13
- package/dist/types-CoXgtTry.d.cts +0 -51
- package/dist/types-CoXgtTry.d.ts +0 -51
package/dist/node/index.cjs
CHANGED
|
@@ -33,6 +33,24 @@ async function verifySignedPayload(token, jwksUrl, expectedAudience) {
|
|
|
33
33
|
});
|
|
34
34
|
return payload;
|
|
35
35
|
}
|
|
36
|
+
async function verifyAccessToken(accessToken, jwksUrl) {
|
|
37
|
+
const JWKS = (0, import_jose.createRemoteJWKSet)(new URL(jwksUrl));
|
|
38
|
+
const { payload } = await (0, import_jose.jwtVerify)(accessToken, JWKS);
|
|
39
|
+
if (!payload.sub || !payload.jti) {
|
|
40
|
+
throw new Error("Invalid token structure: missing sub or jti");
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
sub: payload.sub,
|
|
44
|
+
jti: payload.jti,
|
|
45
|
+
iss: payload.iss,
|
|
46
|
+
aud: payload.aud || "",
|
|
47
|
+
exp: payload.exp,
|
|
48
|
+
iat: payload.iat,
|
|
49
|
+
tenants: payload.tenants || [],
|
|
50
|
+
systemRole: payload.systemRole || "user",
|
|
51
|
+
deviceFingerprint: payload.deviceFingerprint
|
|
52
|
+
};
|
|
53
|
+
}
|
|
36
54
|
|
|
37
55
|
// src/node/SsoClient.ts
|
|
38
56
|
var BigsoSsoClient = class {
|
|
@@ -41,126 +59,79 @@ var BigsoSsoClient = class {
|
|
|
41
59
|
this.appId = options.appId;
|
|
42
60
|
this.ssoJwksUrl = options.ssoJwksUrl;
|
|
43
61
|
}
|
|
44
|
-
/**
|
|
45
|
-
* Verify a signed payload (JWS) against the SSO's JWKS
|
|
46
|
-
* @param token - The compact JWS token
|
|
47
|
-
* @param expectedAudience - The expected audience (app origin)
|
|
48
|
-
* @returns The verified payload
|
|
49
|
-
*/
|
|
50
62
|
async verifySignedPayload(token, expectedAudience) {
|
|
51
63
|
if (!this.ssoJwksUrl) {
|
|
52
64
|
throw new Error("ssoJwksUrl is required for verifySignedPayload");
|
|
53
65
|
}
|
|
54
66
|
return await verifySignedPayload(token, this.ssoJwksUrl, expectedAudience);
|
|
55
67
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
*/
|
|
61
|
-
async validateSessionToken(sessionToken) {
|
|
68
|
+
async validateAccessToken(accessToken) {
|
|
69
|
+
if (!this.ssoJwksUrl) {
|
|
70
|
+
throw new Error("ssoJwksUrl is required for validateAccessToken");
|
|
71
|
+
}
|
|
62
72
|
try {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
headers: {
|
|
66
|
-
"Content-Type": "application/json"
|
|
67
|
-
},
|
|
68
|
-
body: JSON.stringify({
|
|
69
|
-
sessionToken,
|
|
70
|
-
appId: this.appId
|
|
71
|
-
})
|
|
72
|
-
// Node 18+ allows abort signals to enforce timeout, but we will rely on native fetch timeout if available or no timeout for simplicity.
|
|
73
|
-
// In production, we might want to implement an AbortController wrapper.
|
|
74
|
-
});
|
|
75
|
-
if (!response.ok) {
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
const data = await response.json();
|
|
79
|
-
if (data.valid) {
|
|
80
|
-
return {
|
|
81
|
-
user: data.user,
|
|
82
|
-
tenant: data.tenant,
|
|
83
|
-
appId: data.appId,
|
|
84
|
-
expiresAt: data.expiresAt
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
return null;
|
|
88
|
-
} catch (error) {
|
|
89
|
-
console.error("\u274C [BigsoSsoClient] Error validating session:", error instanceof Error ? error.message : error);
|
|
73
|
+
return await verifyAccessToken(accessToken, this.ssoJwksUrl);
|
|
74
|
+
} catch {
|
|
90
75
|
return null;
|
|
91
76
|
}
|
|
92
77
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
*/
|
|
98
|
-
async exchangeCodeForToken(code) {
|
|
99
|
-
const response = await fetch(`${this.ssoBackendUrl}/api/v1/auth/token`, {
|
|
78
|
+
async login(emailOrNuid, password) {
|
|
79
|
+
const isEmail = emailOrNuid.includes("@");
|
|
80
|
+
const payload = isEmail ? { email: emailOrNuid, password } : { nuid: emailOrNuid, password };
|
|
81
|
+
const response = await fetch(`${this.ssoBackendUrl}/api/v2/auth/login`, {
|
|
100
82
|
method: "POST",
|
|
101
|
-
headers: {
|
|
102
|
-
|
|
103
|
-
|
|
83
|
+
headers: { "Content-Type": "application/json" },
|
|
84
|
+
body: JSON.stringify(payload),
|
|
85
|
+
credentials: "include"
|
|
86
|
+
});
|
|
87
|
+
if (!response.ok) {
|
|
88
|
+
const err = await response.json().catch(() => ({}));
|
|
89
|
+
throw new Error(err.message || "Login failed");
|
|
90
|
+
}
|
|
91
|
+
return await response.json();
|
|
92
|
+
}
|
|
93
|
+
async exchangeCode(code, codeVerifier) {
|
|
94
|
+
const response = await fetch(`${this.ssoBackendUrl}/api/v2/auth/exchange`, {
|
|
95
|
+
method: "POST",
|
|
96
|
+
headers: { "Content-Type": "application/json" },
|
|
104
97
|
body: JSON.stringify({
|
|
105
|
-
|
|
106
|
-
appId: this.appId
|
|
107
|
-
|
|
98
|
+
code,
|
|
99
|
+
appId: this.appId,
|
|
100
|
+
codeVerifier
|
|
101
|
+
}),
|
|
102
|
+
credentials: "include"
|
|
108
103
|
});
|
|
109
104
|
if (!response.ok) {
|
|
110
|
-
const
|
|
111
|
-
throw new Error(
|
|
105
|
+
const err = await response.json().catch(() => ({}));
|
|
106
|
+
throw new Error(err.message || "Token exchange failed");
|
|
112
107
|
}
|
|
113
108
|
return await response.json();
|
|
114
109
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
* @param sessionToken - The active session token
|
|
118
|
-
*/
|
|
119
|
-
async revokeSession(sessionToken) {
|
|
120
|
-
const response = await fetch(`${this.ssoBackendUrl}/api/v1/session/revoke`, {
|
|
110
|
+
async refreshTokens() {
|
|
111
|
+
const response = await fetch(`${this.ssoBackendUrl}/api/v2/auth/refresh`, {
|
|
121
112
|
method: "POST",
|
|
122
|
-
headers: {
|
|
123
|
-
|
|
124
|
-
"Authorization": `Bearer ${sessionToken}`
|
|
125
|
-
}
|
|
113
|
+
headers: { "Content-Type": "application/json" },
|
|
114
|
+
credentials: "include"
|
|
126
115
|
});
|
|
127
116
|
if (!response.ok) {
|
|
128
|
-
|
|
117
|
+
const err = await response.json().catch(() => ({}));
|
|
118
|
+
throw new Error(err.message || "Token refresh failed");
|
|
129
119
|
}
|
|
120
|
+
return await response.json();
|
|
130
121
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
refreshToken,
|
|
145
|
-
appId: this.appId
|
|
146
|
-
})
|
|
147
|
-
});
|
|
148
|
-
if (!response.ok) {
|
|
149
|
-
return null;
|
|
150
|
-
}
|
|
151
|
-
const data = await response.json();
|
|
152
|
-
if (data.success) {
|
|
153
|
-
return {
|
|
154
|
-
sessionToken: data.sessionToken,
|
|
155
|
-
refreshToken: data.refreshToken,
|
|
156
|
-
expiresAt: data.expiresAt,
|
|
157
|
-
refreshExpiresAt: data.refreshExpiresAt
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
return null;
|
|
161
|
-
} catch (error) {
|
|
162
|
-
console.error("\u274C [BigsoSsoClient] Error refreshing app session:", error instanceof Error ? error.message : error);
|
|
163
|
-
return null;
|
|
122
|
+
async logout(accessToken, revokeAll = false) {
|
|
123
|
+
const response = await fetch(`${this.ssoBackendUrl}/api/v2/auth/logout`, {
|
|
124
|
+
method: "POST",
|
|
125
|
+
headers: {
|
|
126
|
+
"Content-Type": "application/json",
|
|
127
|
+
"Authorization": `Bearer ${accessToken}`
|
|
128
|
+
},
|
|
129
|
+
body: JSON.stringify({ revokeAll }),
|
|
130
|
+
credentials: "include"
|
|
131
|
+
});
|
|
132
|
+
if (!response.ok) {
|
|
133
|
+
const err = await response.json().catch(() => ({}));
|
|
134
|
+
throw new Error(err.message || "Logout failed");
|
|
164
135
|
}
|
|
165
136
|
}
|
|
166
137
|
};
|
package/dist/node/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as
|
|
1
|
+
import { S as SsoTokenPayload, b as V2LoginResponse, V as V2ExchangeResponse, c as V2RefreshResponse } from '../types-BQzACpj3.cjs';
|
|
2
2
|
|
|
3
3
|
interface SsoClientOptions {
|
|
4
4
|
ssoBackendUrl: string;
|
|
@@ -10,36 +10,12 @@ declare class BigsoSsoClient {
|
|
|
10
10
|
private appId;
|
|
11
11
|
private ssoJwksUrl?;
|
|
12
12
|
constructor(options: SsoClientOptions);
|
|
13
|
-
/**
|
|
14
|
-
* Verify a signed payload (JWS) against the SSO's JWKS
|
|
15
|
-
* @param token - The compact JWS token
|
|
16
|
-
* @param expectedAudience - The expected audience (app origin)
|
|
17
|
-
* @returns The verified payload
|
|
18
|
-
*/
|
|
19
13
|
verifySignedPayload(token: string, expectedAudience: string): Promise<any>;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
validateSessionToken(sessionToken: string): Promise<SsoSessionData | null>;
|
|
26
|
-
/**
|
|
27
|
-
* Exchange authorization code for session token from SSO
|
|
28
|
-
* @param code - The auth code
|
|
29
|
-
* @returns The SSO exchange response
|
|
30
|
-
*/
|
|
31
|
-
exchangeCodeForToken(code: string): Promise<SsoExchangeResponse>;
|
|
32
|
-
/**
|
|
33
|
-
* Revoke session in SSO backend
|
|
34
|
-
* @param sessionToken - The active session token
|
|
35
|
-
*/
|
|
36
|
-
revokeSession(sessionToken: string): Promise<void>;
|
|
37
|
-
/**
|
|
38
|
-
* Refreshes the application session using a refresh token
|
|
39
|
-
* @param refreshToken - The stored refresh token
|
|
40
|
-
* @returns The new session tokens or null if failed
|
|
41
|
-
*/
|
|
42
|
-
refreshAppSession(refreshToken: string): Promise<SsoRefreshData | null>;
|
|
14
|
+
validateAccessToken(accessToken: string): Promise<SsoTokenPayload | null>;
|
|
15
|
+
login(emailOrNuid: string, password: string): Promise<V2LoginResponse>;
|
|
16
|
+
exchangeCode(code: string, codeVerifier: string): Promise<V2ExchangeResponse>;
|
|
17
|
+
refreshTokens(): Promise<V2RefreshResponse>;
|
|
18
|
+
logout(accessToken: string, revokeAll?: boolean): Promise<void>;
|
|
43
19
|
}
|
|
44
20
|
|
|
45
21
|
export { BigsoSsoClient, type SsoClientOptions };
|
package/dist/node/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as
|
|
1
|
+
import { S as SsoTokenPayload, b as V2LoginResponse, V as V2ExchangeResponse, c as V2RefreshResponse } from '../types-BQzACpj3.js';
|
|
2
2
|
|
|
3
3
|
interface SsoClientOptions {
|
|
4
4
|
ssoBackendUrl: string;
|
|
@@ -10,36 +10,12 @@ declare class BigsoSsoClient {
|
|
|
10
10
|
private appId;
|
|
11
11
|
private ssoJwksUrl?;
|
|
12
12
|
constructor(options: SsoClientOptions);
|
|
13
|
-
/**
|
|
14
|
-
* Verify a signed payload (JWS) against the SSO's JWKS
|
|
15
|
-
* @param token - The compact JWS token
|
|
16
|
-
* @param expectedAudience - The expected audience (app origin)
|
|
17
|
-
* @returns The verified payload
|
|
18
|
-
*/
|
|
19
13
|
verifySignedPayload(token: string, expectedAudience: string): Promise<any>;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
validateSessionToken(sessionToken: string): Promise<SsoSessionData | null>;
|
|
26
|
-
/**
|
|
27
|
-
* Exchange authorization code for session token from SSO
|
|
28
|
-
* @param code - The auth code
|
|
29
|
-
* @returns The SSO exchange response
|
|
30
|
-
*/
|
|
31
|
-
exchangeCodeForToken(code: string): Promise<SsoExchangeResponse>;
|
|
32
|
-
/**
|
|
33
|
-
* Revoke session in SSO backend
|
|
34
|
-
* @param sessionToken - The active session token
|
|
35
|
-
*/
|
|
36
|
-
revokeSession(sessionToken: string): Promise<void>;
|
|
37
|
-
/**
|
|
38
|
-
* Refreshes the application session using a refresh token
|
|
39
|
-
* @param refreshToken - The stored refresh token
|
|
40
|
-
* @returns The new session tokens or null if failed
|
|
41
|
-
*/
|
|
42
|
-
refreshAppSession(refreshToken: string): Promise<SsoRefreshData | null>;
|
|
14
|
+
validateAccessToken(accessToken: string): Promise<SsoTokenPayload | null>;
|
|
15
|
+
login(emailOrNuid: string, password: string): Promise<V2LoginResponse>;
|
|
16
|
+
exchangeCode(code: string, codeVerifier: string): Promise<V2ExchangeResponse>;
|
|
17
|
+
refreshTokens(): Promise<V2RefreshResponse>;
|
|
18
|
+
logout(accessToken: string, revokeAll?: boolean): Promise<void>;
|
|
43
19
|
}
|
|
44
20
|
|
|
45
21
|
export { BigsoSsoClient, type SsoClientOptions };
|
package/dist/node/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
verifyAccessToken,
|
|
2
3
|
verifySignedPayload
|
|
3
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-5ECHA2VH.js";
|
|
4
5
|
|
|
5
6
|
// src/node/SsoClient.ts
|
|
6
7
|
var BigsoSsoClient = class {
|
|
@@ -9,126 +10,79 @@ var BigsoSsoClient = class {
|
|
|
9
10
|
this.appId = options.appId;
|
|
10
11
|
this.ssoJwksUrl = options.ssoJwksUrl;
|
|
11
12
|
}
|
|
12
|
-
/**
|
|
13
|
-
* Verify a signed payload (JWS) against the SSO's JWKS
|
|
14
|
-
* @param token - The compact JWS token
|
|
15
|
-
* @param expectedAudience - The expected audience (app origin)
|
|
16
|
-
* @returns The verified payload
|
|
17
|
-
*/
|
|
18
13
|
async verifySignedPayload(token, expectedAudience) {
|
|
19
14
|
if (!this.ssoJwksUrl) {
|
|
20
15
|
throw new Error("ssoJwksUrl is required for verifySignedPayload");
|
|
21
16
|
}
|
|
22
17
|
return await verifySignedPayload(token, this.ssoJwksUrl, expectedAudience);
|
|
23
18
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
*/
|
|
29
|
-
async validateSessionToken(sessionToken) {
|
|
19
|
+
async validateAccessToken(accessToken) {
|
|
20
|
+
if (!this.ssoJwksUrl) {
|
|
21
|
+
throw new Error("ssoJwksUrl is required for validateAccessToken");
|
|
22
|
+
}
|
|
30
23
|
try {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
headers: {
|
|
34
|
-
"Content-Type": "application/json"
|
|
35
|
-
},
|
|
36
|
-
body: JSON.stringify({
|
|
37
|
-
sessionToken,
|
|
38
|
-
appId: this.appId
|
|
39
|
-
})
|
|
40
|
-
// Node 18+ allows abort signals to enforce timeout, but we will rely on native fetch timeout if available or no timeout for simplicity.
|
|
41
|
-
// In production, we might want to implement an AbortController wrapper.
|
|
42
|
-
});
|
|
43
|
-
if (!response.ok) {
|
|
44
|
-
return null;
|
|
45
|
-
}
|
|
46
|
-
const data = await response.json();
|
|
47
|
-
if (data.valid) {
|
|
48
|
-
return {
|
|
49
|
-
user: data.user,
|
|
50
|
-
tenant: data.tenant,
|
|
51
|
-
appId: data.appId,
|
|
52
|
-
expiresAt: data.expiresAt
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
return null;
|
|
56
|
-
} catch (error) {
|
|
57
|
-
console.error("\u274C [BigsoSsoClient] Error validating session:", error instanceof Error ? error.message : error);
|
|
24
|
+
return await verifyAccessToken(accessToken, this.ssoJwksUrl);
|
|
25
|
+
} catch {
|
|
58
26
|
return null;
|
|
59
27
|
}
|
|
60
28
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
*/
|
|
66
|
-
async exchangeCodeForToken(code) {
|
|
67
|
-
const response = await fetch(`${this.ssoBackendUrl}/api/v1/auth/token`, {
|
|
29
|
+
async login(emailOrNuid, password) {
|
|
30
|
+
const isEmail = emailOrNuid.includes("@");
|
|
31
|
+
const payload = isEmail ? { email: emailOrNuid, password } : { nuid: emailOrNuid, password };
|
|
32
|
+
const response = await fetch(`${this.ssoBackendUrl}/api/v2/auth/login`, {
|
|
68
33
|
method: "POST",
|
|
69
|
-
headers: {
|
|
70
|
-
|
|
71
|
-
|
|
34
|
+
headers: { "Content-Type": "application/json" },
|
|
35
|
+
body: JSON.stringify(payload),
|
|
36
|
+
credentials: "include"
|
|
37
|
+
});
|
|
38
|
+
if (!response.ok) {
|
|
39
|
+
const err = await response.json().catch(() => ({}));
|
|
40
|
+
throw new Error(err.message || "Login failed");
|
|
41
|
+
}
|
|
42
|
+
return await response.json();
|
|
43
|
+
}
|
|
44
|
+
async exchangeCode(code, codeVerifier) {
|
|
45
|
+
const response = await fetch(`${this.ssoBackendUrl}/api/v2/auth/exchange`, {
|
|
46
|
+
method: "POST",
|
|
47
|
+
headers: { "Content-Type": "application/json" },
|
|
72
48
|
body: JSON.stringify({
|
|
73
|
-
|
|
74
|
-
appId: this.appId
|
|
75
|
-
|
|
49
|
+
code,
|
|
50
|
+
appId: this.appId,
|
|
51
|
+
codeVerifier
|
|
52
|
+
}),
|
|
53
|
+
credentials: "include"
|
|
76
54
|
});
|
|
77
55
|
if (!response.ok) {
|
|
78
|
-
const
|
|
79
|
-
throw new Error(
|
|
56
|
+
const err = await response.json().catch(() => ({}));
|
|
57
|
+
throw new Error(err.message || "Token exchange failed");
|
|
80
58
|
}
|
|
81
59
|
return await response.json();
|
|
82
60
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
* @param sessionToken - The active session token
|
|
86
|
-
*/
|
|
87
|
-
async revokeSession(sessionToken) {
|
|
88
|
-
const response = await fetch(`${this.ssoBackendUrl}/api/v1/session/revoke`, {
|
|
61
|
+
async refreshTokens() {
|
|
62
|
+
const response = await fetch(`${this.ssoBackendUrl}/api/v2/auth/refresh`, {
|
|
89
63
|
method: "POST",
|
|
90
|
-
headers: {
|
|
91
|
-
|
|
92
|
-
"Authorization": `Bearer ${sessionToken}`
|
|
93
|
-
}
|
|
64
|
+
headers: { "Content-Type": "application/json" },
|
|
65
|
+
credentials: "include"
|
|
94
66
|
});
|
|
95
67
|
if (!response.ok) {
|
|
96
|
-
|
|
68
|
+
const err = await response.json().catch(() => ({}));
|
|
69
|
+
throw new Error(err.message || "Token refresh failed");
|
|
97
70
|
}
|
|
71
|
+
return await response.json();
|
|
98
72
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
refreshToken,
|
|
113
|
-
appId: this.appId
|
|
114
|
-
})
|
|
115
|
-
});
|
|
116
|
-
if (!response.ok) {
|
|
117
|
-
return null;
|
|
118
|
-
}
|
|
119
|
-
const data = await response.json();
|
|
120
|
-
if (data.success) {
|
|
121
|
-
return {
|
|
122
|
-
sessionToken: data.sessionToken,
|
|
123
|
-
refreshToken: data.refreshToken,
|
|
124
|
-
expiresAt: data.expiresAt,
|
|
125
|
-
refreshExpiresAt: data.refreshExpiresAt
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
return null;
|
|
129
|
-
} catch (error) {
|
|
130
|
-
console.error("\u274C [BigsoSsoClient] Error refreshing app session:", error instanceof Error ? error.message : error);
|
|
131
|
-
return null;
|
|
73
|
+
async logout(accessToken, revokeAll = false) {
|
|
74
|
+
const response = await fetch(`${this.ssoBackendUrl}/api/v2/auth/logout`, {
|
|
75
|
+
method: "POST",
|
|
76
|
+
headers: {
|
|
77
|
+
"Content-Type": "application/json",
|
|
78
|
+
"Authorization": `Bearer ${accessToken}`
|
|
79
|
+
},
|
|
80
|
+
body: JSON.stringify({ revokeAll }),
|
|
81
|
+
credentials: "include"
|
|
82
|
+
});
|
|
83
|
+
if (!response.ok) {
|
|
84
|
+
const err = await response.json().catch(() => ({}));
|
|
85
|
+
throw new Error(err.message || "Logout failed");
|
|
132
86
|
}
|
|
133
87
|
}
|
|
134
88
|
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
interface BigsoAuthOptions {
|
|
2
|
+
clientId: string;
|
|
3
|
+
ssoOrigin: string;
|
|
4
|
+
jwksUrl: string;
|
|
5
|
+
timeout?: number;
|
|
6
|
+
debug?: boolean;
|
|
7
|
+
redirectUri?: string;
|
|
8
|
+
tenantHint?: string;
|
|
9
|
+
theme?: 'light' | 'dark';
|
|
10
|
+
}
|
|
11
|
+
interface SsoUser {
|
|
12
|
+
userId: string;
|
|
13
|
+
email: string;
|
|
14
|
+
firstName: string;
|
|
15
|
+
lastName: string;
|
|
16
|
+
}
|
|
17
|
+
interface SsoTenant {
|
|
18
|
+
tenantId: string;
|
|
19
|
+
name: string;
|
|
20
|
+
slug: string;
|
|
21
|
+
role: string;
|
|
22
|
+
}
|
|
23
|
+
interface SsoTokenPayload {
|
|
24
|
+
sub: string;
|
|
25
|
+
jti: string;
|
|
26
|
+
iss: string;
|
|
27
|
+
aud: string;
|
|
28
|
+
exp: number;
|
|
29
|
+
iat: number;
|
|
30
|
+
tenants: SsoTenant[];
|
|
31
|
+
systemRole: string;
|
|
32
|
+
deviceFingerprint?: string;
|
|
33
|
+
}
|
|
34
|
+
interface V2LoginResponse {
|
|
35
|
+
success: boolean;
|
|
36
|
+
tokens: {
|
|
37
|
+
accessToken: string;
|
|
38
|
+
expiresIn: number;
|
|
39
|
+
};
|
|
40
|
+
user: SsoUser;
|
|
41
|
+
}
|
|
42
|
+
interface V2ExchangeResponse {
|
|
43
|
+
success: boolean;
|
|
44
|
+
tokens: {
|
|
45
|
+
accessToken: string;
|
|
46
|
+
refreshToken: string;
|
|
47
|
+
expiresIn: number;
|
|
48
|
+
};
|
|
49
|
+
user: SsoUser;
|
|
50
|
+
tenant: SsoTenant;
|
|
51
|
+
}
|
|
52
|
+
interface V2RefreshResponse {
|
|
53
|
+
success: boolean;
|
|
54
|
+
tokens: {
|
|
55
|
+
accessToken: string;
|
|
56
|
+
expiresIn: number;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
interface BigsoAuthResult {
|
|
60
|
+
code: string;
|
|
61
|
+
state: string;
|
|
62
|
+
nonce: string;
|
|
63
|
+
codeVerifier: string;
|
|
64
|
+
signed_payload: string;
|
|
65
|
+
tenant?: SsoTenant;
|
|
66
|
+
jti?: string;
|
|
67
|
+
iss?: string;
|
|
68
|
+
aud?: string;
|
|
69
|
+
exp?: number;
|
|
70
|
+
iat?: number;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export type { BigsoAuthOptions as B, SsoTokenPayload as S, V2ExchangeResponse as V, BigsoAuthResult as a, V2LoginResponse as b, V2RefreshResponse as c };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
interface BigsoAuthOptions {
|
|
2
|
+
clientId: string;
|
|
3
|
+
ssoOrigin: string;
|
|
4
|
+
jwksUrl: string;
|
|
5
|
+
timeout?: number;
|
|
6
|
+
debug?: boolean;
|
|
7
|
+
redirectUri?: string;
|
|
8
|
+
tenantHint?: string;
|
|
9
|
+
theme?: 'light' | 'dark';
|
|
10
|
+
}
|
|
11
|
+
interface SsoUser {
|
|
12
|
+
userId: string;
|
|
13
|
+
email: string;
|
|
14
|
+
firstName: string;
|
|
15
|
+
lastName: string;
|
|
16
|
+
}
|
|
17
|
+
interface SsoTenant {
|
|
18
|
+
tenantId: string;
|
|
19
|
+
name: string;
|
|
20
|
+
slug: string;
|
|
21
|
+
role: string;
|
|
22
|
+
}
|
|
23
|
+
interface SsoTokenPayload {
|
|
24
|
+
sub: string;
|
|
25
|
+
jti: string;
|
|
26
|
+
iss: string;
|
|
27
|
+
aud: string;
|
|
28
|
+
exp: number;
|
|
29
|
+
iat: number;
|
|
30
|
+
tenants: SsoTenant[];
|
|
31
|
+
systemRole: string;
|
|
32
|
+
deviceFingerprint?: string;
|
|
33
|
+
}
|
|
34
|
+
interface V2LoginResponse {
|
|
35
|
+
success: boolean;
|
|
36
|
+
tokens: {
|
|
37
|
+
accessToken: string;
|
|
38
|
+
expiresIn: number;
|
|
39
|
+
};
|
|
40
|
+
user: SsoUser;
|
|
41
|
+
}
|
|
42
|
+
interface V2ExchangeResponse {
|
|
43
|
+
success: boolean;
|
|
44
|
+
tokens: {
|
|
45
|
+
accessToken: string;
|
|
46
|
+
refreshToken: string;
|
|
47
|
+
expiresIn: number;
|
|
48
|
+
};
|
|
49
|
+
user: SsoUser;
|
|
50
|
+
tenant: SsoTenant;
|
|
51
|
+
}
|
|
52
|
+
interface V2RefreshResponse {
|
|
53
|
+
success: boolean;
|
|
54
|
+
tokens: {
|
|
55
|
+
accessToken: string;
|
|
56
|
+
expiresIn: number;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
interface BigsoAuthResult {
|
|
60
|
+
code: string;
|
|
61
|
+
state: string;
|
|
62
|
+
nonce: string;
|
|
63
|
+
codeVerifier: string;
|
|
64
|
+
signed_payload: string;
|
|
65
|
+
tenant?: SsoTenant;
|
|
66
|
+
jti?: string;
|
|
67
|
+
iss?: string;
|
|
68
|
+
aud?: string;
|
|
69
|
+
exp?: number;
|
|
70
|
+
iat?: number;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export type { BigsoAuthOptions as B, SsoTokenPayload as S, V2ExchangeResponse as V, BigsoAuthResult as a, V2LoginResponse as b, V2RefreshResponse as c };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bigso/auth-sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "SDK de autenticación para SSO v2
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "SDK de autenticación para SSO v2 - JWT Bearer + PKCE",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/",
|
|
7
7
|
"access": "public"
|
package/dist/chunk-LDDK6SJD.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// src/utils/jws.ts
|
|
2
|
-
import { jwtVerify, createRemoteJWKSet } from "jose";
|
|
3
|
-
async function verifySignedPayload(token, jwksUrl, expectedAudience) {
|
|
4
|
-
const JWKS = createRemoteJWKSet(new URL(jwksUrl));
|
|
5
|
-
const { payload } = await jwtVerify(token, JWKS, {
|
|
6
|
-
audience: expectedAudience
|
|
7
|
-
});
|
|
8
|
-
return payload;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export {
|
|
12
|
-
verifySignedPayload
|
|
13
|
-
};
|