@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 +161 -0
- package/package.json +48 -0
- package/src/core/TheranovaAuth.d.ts +93 -0
- package/src/core/TheranovaAuth.d.ts.map +1 -0
- package/src/core/TheranovaAuth.js +273 -0
- package/src/core/TheranovaAuth.js.map +1 -0
- package/src/core/logout.d.ts +36 -0
- package/src/core/logout.d.ts.map +1 -0
- package/src/core/logout.js +60 -0
- package/src/core/logout.js.map +1 -0
- package/src/core/token-manager.d.ts +43 -0
- package/src/core/token-manager.d.ts.map +1 -0
- package/src/core/token-manager.js +80 -0
- package/src/core/token-manager.js.map +1 -0
- package/src/index.d.ts +31 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.js +31 -0
- package/src/index.js.map +1 -0
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
|
package/src/index.js.map
ADDED
|
@@ -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"}
|