@theranova/auth-sdk 0.1.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 ADDED
@@ -0,0 +1,161 @@
1
+ # @theranova/auth-sdk
2
+
3
+ Theranova Platform OAuth2 Authentication SDK for frontend applications.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @theranova/auth-sdk
9
+ # or
10
+ yarn add @theranova/auth-sdk
11
+ # or
12
+ pnpm add @theranova/auth-sdk
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```typescript
18
+ import { TheranovaAuth } from '@theranova/auth-sdk';
19
+
20
+ const auth = new TheranovaAuth({
21
+ issuer: 'https://auth.theranova.com',
22
+ clientId: 'your-client-id',
23
+ redirectUri: 'https://your-app.com/callback',
24
+ });
25
+
26
+ // Start login flow
27
+ await auth.login();
28
+ ```
29
+
30
+ ## Configuration
31
+
32
+ ```typescript
33
+ interface TheranovaAuthConfig {
34
+ /** Authorization server issuer URL */
35
+ issuer: string;
36
+ /** OAuth2 client ID */
37
+ clientId: string;
38
+ /** Redirect URI for OAuth2 callback */
39
+ redirectUri: string;
40
+ /** OAuth2 scopes (default: openid profile email offline_access) */
41
+ scopes?: string[];
42
+ /** Storage key for tokens (default: theranova_auth_tokens) */
43
+ storageKey?: string;
44
+ /** Post-logout redirect URI */
45
+ postLogoutRedirectUri?: string;
46
+ }
47
+ ```
48
+
49
+ ## Usage
50
+
51
+ ### Login
52
+
53
+ ```typescript
54
+ // Start OAuth2 PKCE login flow
55
+ // This will redirect to the authorization server
56
+ await auth.login();
57
+ ```
58
+
59
+ ### Handle Callback
60
+
61
+ In your callback page:
62
+
63
+ ```typescript
64
+ try {
65
+ const tokens = await auth.handleCallback();
66
+ console.log('Login successful:', tokens);
67
+ // Redirect to your app
68
+ window.location.href = '/dashboard';
69
+ } catch (error) {
70
+ console.error('Login failed:', error);
71
+ }
72
+ ```
73
+
74
+ ### Check Authentication
75
+
76
+ ```typescript
77
+ if (auth.isAuthenticated()) {
78
+ console.log('User is logged in');
79
+ }
80
+ ```
81
+
82
+ ### Get Access Token
83
+
84
+ ```typescript
85
+ // Automatically refreshes if expired
86
+ const token = await auth.getAccessToken();
87
+
88
+ // Use in API calls
89
+ fetch('/api/data', {
90
+ headers: {
91
+ 'Authorization': `Bearer ${token}`,
92
+ },
93
+ });
94
+ ```
95
+
96
+ ### Get User Info
97
+
98
+ ```typescript
99
+ // Get user info from ID token
100
+ const userInfo = auth.getUserInfo();
101
+ console.log('User:', userInfo.name, userInfo.email);
102
+ ```
103
+
104
+ ### Local Logout
105
+
106
+ Clears tokens from the current app only. Other connected apps remain logged in.
107
+
108
+ ```typescript
109
+ auth.logout();
110
+ // Redirect to login page
111
+ window.location.href = '/login';
112
+ ```
113
+
114
+ ### Global Logout (SSO)
115
+
116
+ Logs out from all connected applications via the authorization server.
117
+
118
+ ```typescript
119
+ // Get logout URL (useful if you need to do something before logout)
120
+ const logoutUrl = auth.getGlobalLogoutUrl();
121
+
122
+ // Or logout and redirect immediately
123
+ auth.logoutGlobal();
124
+ ```
125
+
126
+ ## Token Management
127
+
128
+ ### TokenManager
129
+
130
+ For advanced token management:
131
+
132
+ ```typescript
133
+ import { TokenManager } from '@theranova/auth-sdk';
134
+
135
+ const tokenManager = new TokenManager('my-app-tokens');
136
+
137
+ // Get tokens
138
+ const tokens = tokenManager.get();
139
+
140
+ // Check if expired
141
+ if (tokenManager.isExpired()) {
142
+ // Refresh or re-login
143
+ }
144
+
145
+ // Clear tokens
146
+ tokenManager.clear();
147
+ ```
148
+
149
+ ## Important Notes
150
+
151
+ 1. **Device Management**: This SDK handles authentication only. Device management is handled separately by the Theranova Platform.
152
+
153
+ 2. **PKCE**: This SDK uses OAuth2 with PKCE (Proof Key for Code Exchange) for enhanced security in public clients (browser apps).
154
+
155
+ 3. **JWT Access Tokens**: The Theranova Platform issues JWT access tokens. Opaque tokens are not supported.
156
+
157
+ 4. **SSO Logout**: When using `logoutGlobal()`, all connected applications will be logged out via OIDC front-channel or back-channel logout.
158
+
159
+ ## License
160
+
161
+ MIT
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@theranova/auth-sdk",
3
+ "version": "0.1.0",
4
+ "description": "Theranova Platform OAuth2 Authentication SDK for frontend applications",
5
+ "main": "./src/index.js",
6
+ "types": "./src/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./src/index.js",
10
+ "require": "./src/index.js",
11
+ "types": "./src/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "src"
16
+ ],
17
+ "keywords": [
18
+ "theranova",
19
+ "oauth2",
20
+ "authentication",
21
+ "sso",
22
+ "pkce",
23
+ "oidc"
24
+ ],
25
+ "author": "Theranova",
26
+ "license": "MIT",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/theranova/hopsys.git",
30
+ "directory": "libs/theranova/auth-sdk"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
35
+ "peerDependencies": {
36
+ "react": ">=18.0.0"
37
+ },
38
+ "peerDependenciesMeta": {
39
+ "react": {
40
+ "optional": true
41
+ }
42
+ },
43
+ "devDependencies": {
44
+ "typescript": "^5.0.0"
45
+ },
46
+ "module": "./src/index.js",
47
+ "type": "module"
48
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * TheranovaAuth
3
+ * Main class for OAuth2 PKCE authentication
4
+ */
5
+ import { type TokenStorage } from './token-manager';
6
+ export interface TheranovaAuthConfig {
7
+ /** Authorization server issuer URL (e.g., https://auth.theranova.com) */
8
+ issuer: string;
9
+ /** OAuth2 client ID */
10
+ clientId: string;
11
+ /** Redirect URI for OAuth2 callback */
12
+ redirectUri: string;
13
+ /** OAuth2 scopes (default: openid profile email offline_access) */
14
+ scopes?: string[];
15
+ /** Storage key for tokens (default: theranova_auth_tokens) */
16
+ storageKey?: string;
17
+ /** Post-logout redirect URI */
18
+ postLogoutRedirectUri?: string;
19
+ }
20
+ export interface TheranovaAuthTokens {
21
+ accessToken: string;
22
+ refreshToken?: string;
23
+ idToken?: string;
24
+ expiresIn: number;
25
+ tokenType: string;
26
+ }
27
+ export declare class TheranovaAuth {
28
+ private config;
29
+ private tokenManager;
30
+ constructor(config: TheranovaAuthConfig);
31
+ /**
32
+ * Start OAuth2 PKCE login flow
33
+ * Generates PKCE challenge and redirects to authorization server
34
+ */
35
+ login(): Promise<void>;
36
+ /**
37
+ * Handle OAuth2 callback
38
+ * Exchanges authorization code for tokens
39
+ *
40
+ * @returns The tokens if successful, null if there was an error
41
+ */
42
+ handleCallback(): Promise<TheranovaAuthTokens | null>;
43
+ /**
44
+ * Exchange authorization code for tokens
45
+ */
46
+ private exchangeCodeForTokens;
47
+ /**
48
+ * Refresh access token using refresh token
49
+ */
50
+ refreshAccessToken(): Promise<TheranovaAuthTokens | null>;
51
+ /**
52
+ * Get current access token (refreshes if expired)
53
+ */
54
+ getAccessToken(): Promise<string | null>;
55
+ /**
56
+ * Get stored tokens
57
+ */
58
+ getTokens(): TokenStorage | null;
59
+ /**
60
+ * Check if user is authenticated
61
+ */
62
+ isAuthenticated(): boolean;
63
+ /**
64
+ * Local logout (clears tokens from this app only)
65
+ */
66
+ logout(): void;
67
+ /**
68
+ * Global logout (SSO logout - logs out from all connected apps)
69
+ * Returns the logout URL to redirect to
70
+ */
71
+ getGlobalLogoutUrl(): string | null;
72
+ /**
73
+ * Perform global logout and redirect
74
+ */
75
+ logoutGlobal(): void;
76
+ /**
77
+ * Get user info from ID token
78
+ */
79
+ getUserInfo(): Record<string, unknown> | null;
80
+ /**
81
+ * Generate random string for state and code verifier
82
+ */
83
+ private generateRandomString;
84
+ /**
85
+ * Generate PKCE code challenge from verifier
86
+ */
87
+ private generateCodeChallenge;
88
+ /**
89
+ * Base64 URL encode
90
+ */
91
+ private base64UrlEncode;
92
+ }
93
+ //# sourceMappingURL=TheranovaAuth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TheranovaAuth.d.ts","sourceRoot":"","sources":["../../../../../../libs/theranova/auth-sdk/src/core/TheranovaAuth.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAGlE,MAAM,WAAW,mBAAmB;IAClC,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf,uBAAuB;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAUD,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,YAAY,CAAe;gBAEvB,MAAM,EAAE,mBAAmB;IAQvC;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA8B5B;;;;;OAKG;IACG,cAAc,IAAI,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAmD3D;;OAEG;YACW,qBAAqB;IAiCnC;;OAEG;IACG,kBAAkB,IAAI,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAoD/D;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAY9C;;OAEG;IACH,SAAS,IAAI,YAAY,GAAG,IAAI;IAIhC;;OAEG;IACH,eAAe,IAAI,OAAO;IAI1B;;OAEG;IACH,MAAM,IAAI,IAAI;IAId;;;OAGG;IACH,kBAAkB,IAAI,MAAM,GAAG,IAAI;IAQnC;;OAEG;IACH,YAAY,IAAI,IAAI;IAQpB;;OAEG;IACH,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAkB7C;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAM5B;;OAEG;YACW,qBAAqB;IAOnC;;OAEG;IACH,OAAO,CAAC,eAAe;CAUxB"}
@@ -0,0 +1,273 @@
1
+ /**
2
+ * TheranovaAuth
3
+ * Main class for OAuth2 PKCE authentication
4
+ */
5
+ import { TokenManager } from './token-manager';
6
+ import { logout as localLogout, logoutGlobal, logoutAndRedirect } from './logout';
7
+ export class TheranovaAuth {
8
+ constructor(config) {
9
+ this.config = {
10
+ ...config,
11
+ scopes: config.scopes || ['openid', 'profile', 'email', 'offline_access'],
12
+ };
13
+ this.tokenManager = new TokenManager(config.storageKey);
14
+ }
15
+ /**
16
+ * Start OAuth2 PKCE login flow
17
+ * Generates PKCE challenge and redirects to authorization server
18
+ */
19
+ async login() {
20
+ // Generate state for CSRF protection
21
+ const state = this.generateRandomString(32);
22
+ // Generate PKCE code verifier and challenge
23
+ const codeVerifier = this.generateRandomString(64);
24
+ const codeChallenge = await this.generateCodeChallenge(codeVerifier);
25
+ // Store state and code verifier in sessionStorage
26
+ if (typeof sessionStorage !== 'undefined') {
27
+ sessionStorage.setItem('oauth2_state', state);
28
+ sessionStorage.setItem('oauth2_code_verifier', codeVerifier);
29
+ }
30
+ // Build authorization URL
31
+ const authUrl = new URL('/auth', this.config.issuer);
32
+ authUrl.searchParams.set('response_type', 'code');
33
+ authUrl.searchParams.set('client_id', this.config.clientId);
34
+ authUrl.searchParams.set('redirect_uri', this.config.redirectUri);
35
+ authUrl.searchParams.set('scope', this.config.scopes.join(' '));
36
+ authUrl.searchParams.set('state', state);
37
+ authUrl.searchParams.set('code_challenge', codeChallenge);
38
+ authUrl.searchParams.set('code_challenge_method', 'S256');
39
+ // Redirect to authorization server
40
+ if (typeof window !== 'undefined') {
41
+ window.location.href = authUrl.toString();
42
+ }
43
+ }
44
+ /**
45
+ * Handle OAuth2 callback
46
+ * Exchanges authorization code for tokens
47
+ *
48
+ * @returns The tokens if successful, null if there was an error
49
+ */
50
+ async handleCallback() {
51
+ if (typeof window === 'undefined') {
52
+ return null;
53
+ }
54
+ const urlParams = new URLSearchParams(window.location.search);
55
+ const code = urlParams.get('code');
56
+ const state = urlParams.get('state');
57
+ const error = urlParams.get('error');
58
+ const errorDescription = urlParams.get('error_description');
59
+ // Check for errors
60
+ if (error) {
61
+ console.error('[TheranovaAuth] OAuth2 error:', error, errorDescription);
62
+ throw new Error(errorDescription || error);
63
+ }
64
+ if (!code) {
65
+ throw new Error('Authorization code not found in callback URL');
66
+ }
67
+ // Validate state
68
+ const savedState = sessionStorage.getItem('oauth2_state');
69
+ if (state !== savedState) {
70
+ throw new Error('State mismatch - possible CSRF attack');
71
+ }
72
+ // Get code verifier
73
+ const codeVerifier = sessionStorage.getItem('oauth2_code_verifier');
74
+ if (!codeVerifier) {
75
+ throw new Error('Code verifier not found. Please try logging in again.');
76
+ }
77
+ // Exchange code for tokens
78
+ const tokens = await this.exchangeCodeForTokens(code, codeVerifier);
79
+ // Save tokens
80
+ this.tokenManager.save({
81
+ accessToken: tokens.accessToken,
82
+ refreshToken: tokens.refreshToken,
83
+ idToken: tokens.idToken,
84
+ expiresAt: Date.now() + tokens.expiresIn * 1000,
85
+ });
86
+ // Clean up sessionStorage
87
+ sessionStorage.removeItem('oauth2_state');
88
+ sessionStorage.removeItem('oauth2_code_verifier');
89
+ return tokens;
90
+ }
91
+ /**
92
+ * Exchange authorization code for tokens
93
+ */
94
+ async exchangeCodeForTokens(code, codeVerifier) {
95
+ const tokenUrl = new URL('/token', this.config.issuer);
96
+ const response = await fetch(tokenUrl.toString(), {
97
+ method: 'POST',
98
+ headers: {
99
+ 'Content-Type': 'application/x-www-form-urlencoded',
100
+ },
101
+ body: new URLSearchParams({
102
+ grant_type: 'authorization_code',
103
+ code,
104
+ redirect_uri: this.config.redirectUri,
105
+ client_id: this.config.clientId,
106
+ code_verifier: codeVerifier,
107
+ }),
108
+ });
109
+ if (!response.ok) {
110
+ const errorData = await response.json().catch(() => ({}));
111
+ throw new Error(errorData.error_description || errorData.error || 'Token exchange failed');
112
+ }
113
+ const data = await response.json();
114
+ return {
115
+ accessToken: data.access_token,
116
+ refreshToken: data.refresh_token,
117
+ idToken: data.id_token,
118
+ expiresIn: data.expires_in,
119
+ tokenType: data.token_type,
120
+ };
121
+ }
122
+ /**
123
+ * Refresh access token using refresh token
124
+ */
125
+ async refreshAccessToken() {
126
+ const refreshToken = this.tokenManager.getRefreshToken();
127
+ if (!refreshToken) {
128
+ return null;
129
+ }
130
+ const tokenUrl = new URL('/token', this.config.issuer);
131
+ try {
132
+ const response = await fetch(tokenUrl.toString(), {
133
+ method: 'POST',
134
+ headers: {
135
+ 'Content-Type': 'application/x-www-form-urlencoded',
136
+ },
137
+ body: new URLSearchParams({
138
+ grant_type: 'refresh_token',
139
+ refresh_token: refreshToken,
140
+ client_id: this.config.clientId,
141
+ }),
142
+ });
143
+ if (!response.ok) {
144
+ // Refresh failed, clear tokens
145
+ this.tokenManager.clear();
146
+ return null;
147
+ }
148
+ const data = await response.json();
149
+ const tokens = {
150
+ accessToken: data.access_token,
151
+ refreshToken: data.refresh_token || refreshToken,
152
+ idToken: data.id_token,
153
+ expiresIn: data.expires_in,
154
+ tokenType: data.token_type,
155
+ };
156
+ // Save new tokens
157
+ this.tokenManager.save({
158
+ accessToken: tokens.accessToken,
159
+ refreshToken: tokens.refreshToken,
160
+ idToken: tokens.idToken,
161
+ expiresAt: Date.now() + tokens.expiresIn * 1000,
162
+ });
163
+ return tokens;
164
+ }
165
+ catch {
166
+ this.tokenManager.clear();
167
+ return null;
168
+ }
169
+ }
170
+ /**
171
+ * Get current access token (refreshes if expired)
172
+ */
173
+ async getAccessToken() {
174
+ // Try to get non-expired token
175
+ let token = this.tokenManager.getAccessToken();
176
+ if (token) {
177
+ return token;
178
+ }
179
+ // Token expired, try to refresh
180
+ const newTokens = await this.refreshAccessToken();
181
+ return newTokens?.accessToken || null;
182
+ }
183
+ /**
184
+ * Get stored tokens
185
+ */
186
+ getTokens() {
187
+ return this.tokenManager.get();
188
+ }
189
+ /**
190
+ * Check if user is authenticated
191
+ */
192
+ isAuthenticated() {
193
+ return !this.tokenManager.isExpired();
194
+ }
195
+ /**
196
+ * Local logout (clears tokens from this app only)
197
+ */
198
+ logout() {
199
+ localLogout({ tokenManager: this.tokenManager });
200
+ }
201
+ /**
202
+ * Global logout (SSO logout - logs out from all connected apps)
203
+ * Returns the logout URL to redirect to
204
+ */
205
+ getGlobalLogoutUrl() {
206
+ return logoutGlobal({
207
+ tokenManager: this.tokenManager,
208
+ issuer: this.config.issuer,
209
+ postLogoutRedirectUri: this.config.postLogoutRedirectUri || this.config.redirectUri,
210
+ });
211
+ }
212
+ /**
213
+ * Perform global logout and redirect
214
+ */
215
+ logoutGlobal() {
216
+ logoutAndRedirect({
217
+ tokenManager: this.tokenManager,
218
+ issuer: this.config.issuer,
219
+ postLogoutRedirectUri: this.config.postLogoutRedirectUri || this.config.redirectUri,
220
+ });
221
+ }
222
+ /**
223
+ * Get user info from ID token
224
+ */
225
+ getUserInfo() {
226
+ const idToken = this.tokenManager.getIdToken();
227
+ if (!idToken) {
228
+ return null;
229
+ }
230
+ try {
231
+ const parts = idToken.split('.');
232
+ if (parts.length !== 3) {
233
+ return null;
234
+ }
235
+ const payload = JSON.parse(atob(parts[1]));
236
+ return payload;
237
+ }
238
+ catch {
239
+ return null;
240
+ }
241
+ }
242
+ /**
243
+ * Generate random string for state and code verifier
244
+ */
245
+ generateRandomString(length) {
246
+ const array = new Uint8Array(length);
247
+ crypto.getRandomValues(array);
248
+ return Array.from(array, (byte) => byte.toString(16).padStart(2, '0')).join('').slice(0, length);
249
+ }
250
+ /**
251
+ * Generate PKCE code challenge from verifier
252
+ */
253
+ async generateCodeChallenge(verifier) {
254
+ const encoder = new TextEncoder();
255
+ const data = encoder.encode(verifier);
256
+ const digest = await crypto.subtle.digest('SHA-256', data);
257
+ return this.base64UrlEncode(new Uint8Array(digest));
258
+ }
259
+ /**
260
+ * Base64 URL encode
261
+ */
262
+ base64UrlEncode(buffer) {
263
+ let binary = '';
264
+ for (let i = 0; i < buffer.length; i++) {
265
+ binary += String.fromCharCode(buffer[i]);
266
+ }
267
+ return btoa(binary)
268
+ .replace(/\+/g, '-')
269
+ .replace(/\//g, '_')
270
+ .replace(/=/g, '');
271
+ }
272
+ }
273
+ //# sourceMappingURL=TheranovaAuth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TheranovaAuth.js","sourceRoot":"","sources":["../../../../../../libs/theranova/auth-sdk/src/core/TheranovaAuth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Logout utilities
3
+ * Handles local and global (SSO) logout
4
+ */
5
+ import { TokenManager } from './token-manager';
6
+ export interface LogoutOptions {
7
+ /** Token manager instance */
8
+ tokenManager?: TokenManager;
9
+ /** Custom storage key if not using default TokenManager */
10
+ storageKey?: string;
11
+ /** Authorization server issuer URL */
12
+ issuer?: string;
13
+ /** Post-logout redirect URI */
14
+ postLogoutRedirectUri?: string;
15
+ /** ID token for global logout */
16
+ idToken?: string;
17
+ }
18
+ /**
19
+ * Local logout
20
+ * Clears tokens from localStorage without affecting other apps
21
+ */
22
+ export declare function logout(options?: LogoutOptions): void;
23
+ /**
24
+ * Global logout (SSO logout)
25
+ * Redirects to the authorization server's end_session endpoint
26
+ * This will log out from all connected applications
27
+ *
28
+ * @returns The logout URL to redirect to, or null if issuer is not provided
29
+ */
30
+ export declare function logoutGlobal(options: LogoutOptions): string | null;
31
+ /**
32
+ * Perform global logout and redirect
33
+ * Convenience function that combines logoutGlobal with navigation
34
+ */
35
+ export declare function logoutAndRedirect(options: LogoutOptions): void;
36
+ //# sourceMappingURL=logout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../../../../../libs/theranova/auth-sdk/src/core/logout.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,MAAM,WAAW,aAAa;IAC5B,6BAA6B;IAC7B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,OAAO,GAAE,aAAkB,GAAG,IAAI,CASxD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CA8BlE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAM9D"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Logout utilities
3
+ * Handles local and global (SSO) logout
4
+ */
5
+ import { TokenManager } from './token-manager';
6
+ /**
7
+ * Local logout
8
+ * Clears tokens from localStorage without affecting other apps
9
+ */
10
+ export function logout(options = {}) {
11
+ const tokenManager = options.tokenManager || new TokenManager(options.storageKey);
12
+ tokenManager.clear();
13
+ // Also clear any PKCE state
14
+ if (typeof sessionStorage !== 'undefined') {
15
+ sessionStorage.removeItem('oauth2_state');
16
+ sessionStorage.removeItem('oauth2_code_verifier');
17
+ }
18
+ }
19
+ /**
20
+ * Global logout (SSO logout)
21
+ * Redirects to the authorization server's end_session endpoint
22
+ * This will log out from all connected applications
23
+ *
24
+ * @returns The logout URL to redirect to, or null if issuer is not provided
25
+ */
26
+ export function logoutGlobal(options) {
27
+ const { issuer, postLogoutRedirectUri, idToken, tokenManager, storageKey } = options;
28
+ if (!issuer) {
29
+ console.warn('[TheranovaAuth] Cannot perform global logout: issuer not provided');
30
+ return null;
31
+ }
32
+ // Get ID token from options or storage
33
+ let idTokenHint = idToken;
34
+ if (!idTokenHint) {
35
+ const tm = tokenManager || new TokenManager(storageKey);
36
+ idTokenHint = tm.getIdToken() || undefined;
37
+ }
38
+ // Build end_session URL
39
+ const url = new URL('/session/end', issuer);
40
+ if (idTokenHint) {
41
+ url.searchParams.set('id_token_hint', idTokenHint);
42
+ }
43
+ if (postLogoutRedirectUri) {
44
+ url.searchParams.set('post_logout_redirect_uri', postLogoutRedirectUri);
45
+ }
46
+ // Clear local tokens
47
+ logout({ tokenManager, storageKey });
48
+ return url.toString();
49
+ }
50
+ /**
51
+ * Perform global logout and redirect
52
+ * Convenience function that combines logoutGlobal with navigation
53
+ */
54
+ export function logoutAndRedirect(options) {
55
+ const logoutUrl = logoutGlobal(options);
56
+ if (logoutUrl && typeof window !== 'undefined') {
57
+ window.location.href = logoutUrl;
58
+ }
59
+ }
60
+ //# sourceMappingURL=logout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../../../../../libs/theranova/auth-sdk/src/core/logout.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAe/C;;;GAGG;AACH,MAAM,UAAU,MAAM,CAAC,UAAyB,EAAE;IAChD,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,IAAI,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAClF,YAAY,CAAC,KAAK,EAAE,CAAC;IAErB,4BAA4B;IAC5B,IAAI,OAAO,cAAc,KAAK,WAAW,EAAE,CAAC;QAC1C,cAAc,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;QAC1C,cAAc,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAAC;IACpD,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,OAAsB;IACjD,MAAM,EAAE,MAAM,EAAE,qBAAqB,EAAE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IAErF,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,IAAI,CAAC,mEAAmE,CAAC,CAAC;QAClF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,uCAAuC;IACvC,IAAI,WAAW,GAAG,OAAO,CAAC;IAC1B,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,EAAE,GAAG,YAAY,IAAI,IAAI,YAAY,CAAC,UAAU,CAAC,CAAC;QACxD,WAAW,GAAG,EAAE,CAAC,UAAU,EAAE,IAAI,SAAS,CAAC;IAC7C,CAAC;IAED,wBAAwB;IACxB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IAE5C,IAAI,WAAW,EAAE,CAAC;QAChB,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,qBAAqB,EAAE,CAAC;QAC1B,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,0BAA0B,EAAE,qBAAqB,CAAC,CAAC;IAC1E,CAAC;IAED,qBAAqB;IACrB,MAAM,CAAC,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,CAAC;IAErC,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;AACxB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAsB;IACtD,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IAExC,IAAI,SAAS,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAC/C,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,SAAS,CAAC;IACnC,CAAC;AACH,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Token Manager
3
+ * Handles token storage and retrieval
4
+ */
5
+ export interface TokenStorage {
6
+ accessToken: string;
7
+ refreshToken?: string;
8
+ idToken?: string;
9
+ expiresAt: number;
10
+ }
11
+ export declare class TokenManager {
12
+ private storageKey;
13
+ constructor(storageKey?: string);
14
+ /**
15
+ * Save tokens to localStorage
16
+ */
17
+ save(tokens: TokenStorage): void;
18
+ /**
19
+ * Get tokens from localStorage
20
+ */
21
+ get(): TokenStorage | null;
22
+ /**
23
+ * Clear tokens from localStorage
24
+ */
25
+ clear(): void;
26
+ /**
27
+ * Check if access token is expired
28
+ */
29
+ isExpired(): boolean;
30
+ /**
31
+ * Get access token if not expired
32
+ */
33
+ getAccessToken(): string | null;
34
+ /**
35
+ * Get refresh token
36
+ */
37
+ getRefreshToken(): string | null;
38
+ /**
39
+ * Get ID token
40
+ */
41
+ getIdToken(): string | null;
42
+ }
43
+ //# sourceMappingURL=token-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-manager.d.ts","sourceRoot":"","sources":["../../../../../../libs/theranova/auth-sdk/src/core/token-manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAID,qBAAa,YAAY;IACvB,OAAO,CAAC,UAAU,CAAS;gBAEf,UAAU,GAAE,MAA4B;IAIpD;;OAEG;IACH,IAAI,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAQhC;;OAEG;IACH,GAAG,IAAI,YAAY,GAAG,IAAI;IAiB1B;;OAEG;IACH,KAAK,IAAI,IAAI;IAOb;;OAEG;IACH,SAAS,IAAI,OAAO;IASpB;;OAEG;IACH,cAAc,IAAI,MAAM,GAAG,IAAI;IAO/B;;OAEG;IACH,eAAe,IAAI,MAAM,GAAG,IAAI;IAIhC;;OAEG;IACH,UAAU,IAAI,MAAM,GAAG,IAAI;CAG5B"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Token Manager
3
+ * Handles token storage and retrieval
4
+ */
5
+ const DEFAULT_STORAGE_KEY = 'theranova_auth_tokens';
6
+ export class TokenManager {
7
+ constructor(storageKey = DEFAULT_STORAGE_KEY) {
8
+ this.storageKey = storageKey;
9
+ }
10
+ /**
11
+ * Save tokens to localStorage
12
+ */
13
+ save(tokens) {
14
+ if (typeof localStorage === 'undefined') {
15
+ console.warn('[TokenManager] localStorage is not available');
16
+ return;
17
+ }
18
+ localStorage.setItem(this.storageKey, JSON.stringify(tokens));
19
+ }
20
+ /**
21
+ * Get tokens from localStorage
22
+ */
23
+ get() {
24
+ if (typeof localStorage === 'undefined') {
25
+ return null;
26
+ }
27
+ const stored = localStorage.getItem(this.storageKey);
28
+ if (!stored) {
29
+ return null;
30
+ }
31
+ try {
32
+ return JSON.parse(stored);
33
+ }
34
+ catch {
35
+ return null;
36
+ }
37
+ }
38
+ /**
39
+ * Clear tokens from localStorage
40
+ */
41
+ clear() {
42
+ if (typeof localStorage === 'undefined') {
43
+ return;
44
+ }
45
+ localStorage.removeItem(this.storageKey);
46
+ }
47
+ /**
48
+ * Check if access token is expired
49
+ */
50
+ isExpired() {
51
+ const tokens = this.get();
52
+ if (!tokens) {
53
+ return true;
54
+ }
55
+ // Consider token expired 60 seconds before actual expiry
56
+ return Date.now() >= tokens.expiresAt - 60000;
57
+ }
58
+ /**
59
+ * Get access token if not expired
60
+ */
61
+ getAccessToken() {
62
+ if (this.isExpired()) {
63
+ return null;
64
+ }
65
+ return this.get()?.accessToken || null;
66
+ }
67
+ /**
68
+ * Get refresh token
69
+ */
70
+ getRefreshToken() {
71
+ return this.get()?.refreshToken || null;
72
+ }
73
+ /**
74
+ * Get ID token
75
+ */
76
+ getIdToken() {
77
+ return this.get()?.idToken || null;
78
+ }
79
+ }
80
+ //# sourceMappingURL=token-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-manager.js","sourceRoot":"","sources":["../../../../../../libs/theranova/auth-sdk/src/core/token-manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,MAAM,mBAAmB,GAAG,uBAAuB,CAAC;AAEpD,MAAM,OAAO,YAAY;IAGvB,YAAY,aAAqB,mBAAmB;QAClD,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,IAAI,CAAC,MAAoB;QACvB,IAAI,OAAO,YAAY,KAAK,WAAW,EAAE,CAAC;YACxC,OAAO,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;YAC7D,OAAO;QACT,CAAC;QACD,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAChE,CAAC;IAED;;OAEG;IACH,GAAG;QACD,IAAI,OAAO,YAAY,KAAK,WAAW,EAAE,CAAC;YACxC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACrD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAiB,CAAC;QAC5C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,OAAO,YAAY,KAAK,WAAW,EAAE,CAAC;YACxC,OAAO;QACT,CAAC;QACD,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC3C,CAAC;IAED;;OAEG;IACH,SAAS;QACP,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC1B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QACD,yDAAyD;QACzD,OAAO,IAAI,CAAC,GAAG,EAAE,IAAI,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC;IAChD,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC,GAAG,EAAE,EAAE,WAAW,IAAI,IAAI,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,eAAe;QACb,OAAO,IAAI,CAAC,GAAG,EAAE,EAAE,YAAY,IAAI,IAAI,CAAC;IAC1C,CAAC;IAED;;OAEG;IACH,UAAU;QACR,OAAO,IAAI,CAAC,GAAG,EAAE,EAAE,OAAO,IAAI,IAAI,CAAC;IACrC,CAAC;CACF"}
package/src/index.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Theranova Auth SDK
3
+ * OAuth2 PKCE Authentication SDK for frontend applications
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * import { TheranovaAuth } from '@theranova/auth-sdk';
8
+ *
9
+ * const auth = new TheranovaAuth({
10
+ * issuer: 'https://auth.theranova.com',
11
+ * clientId: 'my-app',
12
+ * redirectUri: 'https://my-app.com/callback',
13
+ * });
14
+ *
15
+ * // Start login flow
16
+ * await auth.login();
17
+ *
18
+ * // Handle callback
19
+ * await auth.handleCallback();
20
+ *
21
+ * // Get current user
22
+ * const user = await auth.getUser();
23
+ *
24
+ * // Logout
25
+ * await auth.logout();
26
+ * ```
27
+ */
28
+ export { TheranovaAuth, type TheranovaAuthConfig, type TheranovaAuthTokens } from './core/TheranovaAuth';
29
+ export { TokenManager, type TokenStorage } from './core/token-manager';
30
+ export { logout, logoutGlobal, type LogoutOptions } from './core/logout';
31
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../libs/theranova/auth-sdk/src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,aAAa,EAAE,KAAK,mBAAmB,EAAE,KAAK,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACzG,OAAO,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC"}
package/src/index.js ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Theranova Auth SDK
3
+ * OAuth2 PKCE Authentication SDK for frontend applications
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * import { TheranovaAuth } from '@theranova/auth-sdk';
8
+ *
9
+ * const auth = new TheranovaAuth({
10
+ * issuer: 'https://auth.theranova.com',
11
+ * clientId: 'my-app',
12
+ * redirectUri: 'https://my-app.com/callback',
13
+ * });
14
+ *
15
+ * // Start login flow
16
+ * await auth.login();
17
+ *
18
+ * // Handle callback
19
+ * await auth.handleCallback();
20
+ *
21
+ * // Get current user
22
+ * const user = await auth.getUser();
23
+ *
24
+ * // Logout
25
+ * await auth.logout();
26
+ * ```
27
+ */
28
+ export { TheranovaAuth } from './core/TheranovaAuth';
29
+ export { TokenManager } from './core/token-manager';
30
+ export { logout, logoutGlobal } from './core/logout';
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../libs/theranova/auth-sdk/src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,aAAa,EAAsD,MAAM,sBAAsB,CAAC;AACzG,OAAO,EAAE,YAAY,EAAqB,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAsB,MAAM,eAAe,CAAC"}