@elogroup-sereduc/ser-front-core-client 1.1.0 → 2.0.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/OAUTH_MIGRATION.md +86 -0
- package/README.md +145 -321
- package/dist/{axios.d.ts → api-client.d.ts} +3 -3
- package/dist/api-client.d.ts.map +1 -0
- package/dist/{axios.js → api-client.js} +11 -11
- package/dist/api-client.js.map +1 -0
- package/dist/auth/bootstrap.d.ts +5 -0
- package/dist/auth/bootstrap.d.ts.map +1 -0
- package/dist/auth/bootstrap.js +28 -0
- package/dist/auth/bootstrap.js.map +1 -0
- package/dist/auth/http-client.d.ts +3 -0
- package/dist/auth/http-client.d.ts.map +1 -0
- package/dist/auth/http-client.js +31 -0
- package/dist/auth/http-client.js.map +1 -0
- package/dist/auth/index.d.ts +18 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +22 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/route-guards.d.ts +14 -0
- package/dist/auth/route-guards.d.ts.map +1 -0
- package/dist/auth/route-guards.js +23 -0
- package/dist/auth/route-guards.js.map +1 -0
- package/dist/auth/ser-oauth-js.d.ts +54 -0
- package/dist/auth/ser-oauth-js.d.ts.map +1 -0
- package/dist/auth/ser-oauth-js.js +405 -0
- package/dist/auth/ser-oauth-js.js.map +1 -0
- package/dist/auth/store.d.ts +14 -0
- package/dist/auth/store.d.ts.map +1 -0
- package/dist/auth/store.js +20 -0
- package/dist/auth/store.js.map +1 -0
- package/dist/index.d.ts +3 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -4
- package/dist/index.js.map +1 -1
- package/dist/keycloak.d.ts +12 -0
- package/dist/keycloak.d.ts.map +1 -1
- package/dist/keycloak.js +226 -9
- package/dist/keycloak.js.map +1 -1
- package/dist/utils/auth.d.ts +8 -0
- package/dist/utils/auth.d.ts.map +1 -1
- package/dist/utils/auth.js +13 -2
- package/dist/utils/auth.js.map +1 -1
- package/package.json +8 -6
- package/public/silent-callback.html +19 -0
- package/public/silent-check-sso.html +30 -0
- package/dist/axios.d.ts.map +0 -1
- package/dist/axios.js.map +0 -1
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Migração para Ser OAuth System
|
|
2
|
+
|
|
3
|
+
Esta biblioteca agora inclui um sistema completo de autenticação OAuth/OIDC (`ser-oauth-js`) além do sistema Keycloak original.
|
|
4
|
+
|
|
5
|
+
## Nova Implementação: Ser OAuth
|
|
6
|
+
|
|
7
|
+
### Características
|
|
8
|
+
|
|
9
|
+
- ✅ **Silent SSO**: Autenticação invisível via iframe
|
|
10
|
+
- ✅ **PKCE S256**: Segurança avançada para SPAs
|
|
11
|
+
- ✅ **Token Refresh**: Renovação automática de tokens
|
|
12
|
+
- ✅ **API Client**: Cliente HTTP com interceptadores automáticos
|
|
13
|
+
- ✅ **Route Guards**: Proteção de rotas para TanStack Router
|
|
14
|
+
- ✅ **Zustand Store**: Gerenciamento de estado reativo
|
|
15
|
+
- ✅ **IDP Hint**: Redirecionamento automático para provedores específicos
|
|
16
|
+
|
|
17
|
+
### Setup Básico
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import {
|
|
21
|
+
createKeycloakAuthFromUrl,
|
|
22
|
+
initAuth,
|
|
23
|
+
useAuthStore,
|
|
24
|
+
} from "@elogroup-sereduc/ser-front-core-client";
|
|
25
|
+
|
|
26
|
+
const kc = createKeycloakAuthFromUrl(
|
|
27
|
+
"https://sso.sereduc.com/realms/colaboradores/protocol/openid-connect/auth",
|
|
28
|
+
"seu-client-id",
|
|
29
|
+
"ser-oidc", // IDP hint opcional
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const authenticated = await initAuth(kc, "/seu-base-path");
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Migração de Projetos
|
|
36
|
+
|
|
37
|
+
1. **Instalar nova versão** da biblioteca
|
|
38
|
+
2. **Copiar `silent-check-sso.html`** para pasta public
|
|
39
|
+
3. **Substituir inicialização** do auth
|
|
40
|
+
4. **Atualizar imports** dos hooks/stores
|
|
41
|
+
5. **Testar Silent SSO** e fluxo completo
|
|
42
|
+
|
|
43
|
+
### Exemplo de Context
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import { useAuthStore } from "@elogroup-sereduc/ser-front-core-client";
|
|
47
|
+
|
|
48
|
+
export function useAuth() {
|
|
49
|
+
const authState = useAuthStore();
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
authenticated: authState.authenticated,
|
|
53
|
+
token: authState.accessToken,
|
|
54
|
+
login: () => kc.login(),
|
|
55
|
+
logout: () => kc.logout(),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### API Client
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
import { createApiClient } from "@elogroup-sereduc/ser-front-core-client";
|
|
64
|
+
|
|
65
|
+
const api = createApiClient(kc, "https://api.sereduc.com");
|
|
66
|
+
|
|
67
|
+
// O cliente automaticamente:
|
|
68
|
+
// - Adiciona Bearer token
|
|
69
|
+
// - Renova em caso de 401
|
|
70
|
+
// - Retenta requisição
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Route Guards
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { createAuthGuard } from "@elogroup-sereduc/ser-front-core-client";
|
|
77
|
+
|
|
78
|
+
const requireAuth = createAuthGuard(kc);
|
|
79
|
+
|
|
80
|
+
export const Route = createFileRoute("/protected")({
|
|
81
|
+
beforeLoad: requireAuth,
|
|
82
|
+
component: ProtectedComponent,
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Ver documentação completa em `src/auth/README.md`.
|
package/README.md
CHANGED
|
@@ -1,405 +1,229 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Ser Auth Library
|
|
2
2
|
|
|
3
|
-
Keycloak-
|
|
3
|
+
Sistema de autenticação OAuth/OIDC compatível com Keycloak, desenvolvido como substituto para keycloak-js com suporte a Silent SSO, PKCE S256, e gerenciamento automático de tokens.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Características
|
|
6
6
|
|
|
7
|
-
- ✅
|
|
8
|
-
- ✅
|
|
9
|
-
- ✅
|
|
10
|
-
- ✅
|
|
11
|
-
- ✅
|
|
12
|
-
- ✅
|
|
13
|
-
- ✅
|
|
7
|
+
- ✅ **Silent SSO**: Autenticação invisível via iframe
|
|
8
|
+
- ✅ **PKCE S256**: Segurança para SPAs (Single Page Applications)
|
|
9
|
+
- ✅ **Token Refresh**: Renovação automática de tokens
|
|
10
|
+
- ✅ **API Client**: Cliente HTTP com interceptadores automáticos
|
|
11
|
+
- ✅ **Route Guards**: Proteção de rotas para frameworks como TanStack Router
|
|
12
|
+
- ✅ **Zustand Store**: Gerenciamento de estado em memória
|
|
13
|
+
- ✅ **IDP Hint**: Suporte a redirecionamento automático para provedores específicos
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## Instalação
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
18
|
npm install @elogroup-sereduc/ser-front-core-client
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
##
|
|
21
|
+
## Setup Básico
|
|
22
22
|
|
|
23
|
-
###
|
|
23
|
+
### 1. Configuração Inicial
|
|
24
24
|
|
|
25
25
|
```typescript
|
|
26
|
-
import {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
keycloak: {
|
|
31
|
-
url: "https://your-keycloak-server",
|
|
32
|
-
realm: "your-realm",
|
|
33
|
-
clientId: "your-client-id",
|
|
34
|
-
},
|
|
35
|
-
api: {
|
|
36
|
-
baseURL: "https://your-api-server",
|
|
37
|
-
},
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
// Use like a normal axios instance
|
|
41
|
-
const users = await apiClient.get("/users");
|
|
42
|
-
const newUser = await apiClient.post("/users", userData);
|
|
43
|
-
```
|
|
26
|
+
import {
|
|
27
|
+
createKeycloakAuthFromUrl,
|
|
28
|
+
initAuth,
|
|
29
|
+
} from "@elogroup-sereduc/ser-front-core-client";
|
|
44
30
|
|
|
45
|
-
|
|
31
|
+
// Criar instância do SerOAuth
|
|
32
|
+
const kc = createKeycloakAuthFromUrl(
|
|
33
|
+
"https://seu-keycloak.com/realms/seu-realm/protocol/openid-connect/auth",
|
|
34
|
+
"seu-client-id",
|
|
35
|
+
"seu-idp-hint", // opcional
|
|
36
|
+
);
|
|
46
37
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const apiClient = createSimpleApiClient("https://your-api-server", {
|
|
51
|
-
url: "https://your-keycloak-server",
|
|
52
|
-
realm: "your-realm",
|
|
53
|
-
clientId: "your-client-id",
|
|
54
|
-
});
|
|
38
|
+
// Inicializar autenticação
|
|
39
|
+
const authenticated = await initAuth(kc, "/seu-base-path");
|
|
55
40
|
```
|
|
56
41
|
|
|
57
|
-
|
|
42
|
+
### 2. Arquivo Silent-Check-SSO
|
|
58
43
|
|
|
59
|
-
|
|
44
|
+
Copie o arquivo `public/silent-check-sso.html` para a pasta `public` da sua aplicação.
|
|
60
45
|
|
|
61
|
-
|
|
46
|
+
### 3. Context de Autenticação (React)
|
|
62
47
|
|
|
63
48
|
```typescript
|
|
64
|
-
|
|
65
|
-
keycloak: {
|
|
66
|
-
url: "https://your-keycloak-server",
|
|
67
|
-
realm: "your-realm",
|
|
68
|
-
clientId: "your-client-id",
|
|
69
|
-
basePath: "/portal-aluno", // Application base path
|
|
70
|
-
},
|
|
71
|
-
api: {
|
|
72
|
-
baseURL: "https://your-api-server",
|
|
73
|
-
},
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
const apiClient = createApiClient(config);
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
The `basePath` is used to construct correct redirect URIs for:
|
|
80
|
-
|
|
81
|
-
- Silent SSO check redirects
|
|
82
|
-
- Login/logout redirects
|
|
83
|
-
- Error handling redirects
|
|
49
|
+
import { useAuthStore } from '@elogroup-sereduc/ser-front-core-client'
|
|
84
50
|
|
|
85
|
-
|
|
51
|
+
export function AuthContext({ children }) {
|
|
52
|
+
const authState = useAuthStore()
|
|
86
53
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
checkLoginIframe?: boolean;
|
|
98
|
-
// ... other KeycloakInitOptions
|
|
99
|
-
};
|
|
54
|
+
return (
|
|
55
|
+
<AuthProvider value={{
|
|
56
|
+
authenticated: authState.authenticated,
|
|
57
|
+
user: extractUserFromToken(authState.idToken),
|
|
58
|
+
login: () => kc.login(),
|
|
59
|
+
logout: () => kc.logout(),
|
|
60
|
+
}}>
|
|
61
|
+
{children}
|
|
62
|
+
</AuthProvider>
|
|
63
|
+
)
|
|
100
64
|
}
|
|
101
65
|
```
|
|
102
66
|
|
|
103
|
-
###
|
|
67
|
+
### 4. Cliente API
|
|
104
68
|
|
|
105
69
|
```typescript
|
|
106
|
-
|
|
107
|
-
baseURL: string; // API base URL
|
|
108
|
-
headers?: Record<string, string>; // Default headers
|
|
109
|
-
withCredentials?: boolean; // Include cookies (default: true)
|
|
110
|
-
onTokenRefreshFailed?: (error: Error) => void; // Custom error handler
|
|
111
|
-
loginRedirectUrl?: string; // Custom login redirect URL
|
|
112
|
-
}
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
### Login Interfaces
|
|
70
|
+
import { createApiClient } from "@elogroup-sereduc/ser-front-core-client";
|
|
116
71
|
|
|
117
|
-
|
|
118
|
-
interface DirectLoginCredentials {
|
|
119
|
-
username: string; // Username for direct login
|
|
120
|
-
password: string; // Password for direct login
|
|
121
|
-
}
|
|
72
|
+
const api = createApiClient(kc, "https://sua-api.com");
|
|
122
73
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
prompt?: "none" | "login" | "consent" | "select_account"; // OIDC prompt parameter
|
|
128
|
-
}
|
|
74
|
+
// O cliente automaticamente:
|
|
75
|
+
// - Adiciona Bearer token nos headers
|
|
76
|
+
// - Renova token em caso de 401
|
|
77
|
+
// - Retenta requisição com novo token
|
|
129
78
|
```
|
|
130
79
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
### Login Types
|
|
134
|
-
|
|
135
|
-
This package supports two types of login:
|
|
136
|
-
|
|
137
|
-
1. **External Login (Default)**: Redirects to Keycloak login page
|
|
138
|
-
2. **Direct Login (Internal Users)**: Uses username/password without external redirect
|
|
139
|
-
|
|
140
|
-
### External Login (Standard Flow)
|
|
80
|
+
### 5. Route Guards
|
|
141
81
|
|
|
142
82
|
```typescript
|
|
143
|
-
import {
|
|
83
|
+
import { createAuthGuard } from "@elogroup-sereduc/ser-front-core-client";
|
|
84
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
144
85
|
|
|
145
|
-
const
|
|
146
|
-
url: "https://your-keycloak-server",
|
|
147
|
-
realm: "your-realm",
|
|
148
|
-
clientId: "your-client-id",
|
|
149
|
-
});
|
|
86
|
+
const requireAuth = createAuthGuard(kc);
|
|
150
87
|
|
|
151
|
-
|
|
152
|
-
|
|
88
|
+
export const Route = createFileRoute("/protected")({
|
|
89
|
+
beforeLoad: requireAuth,
|
|
90
|
+
component: ProtectedComponent,
|
|
91
|
+
});
|
|
153
92
|
```
|
|
154
93
|
|
|
155
|
-
|
|
94
|
+
## API Reference
|
|
156
95
|
|
|
157
|
-
|
|
96
|
+
### SerOAuth
|
|
158
97
|
|
|
159
98
|
```typescript
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
type DirectLoginCredentials,
|
|
163
|
-
DirectLoginError,
|
|
164
|
-
} from "@elogroup-sereduc/ser-front-core-client";
|
|
165
|
-
|
|
166
|
-
const authService = await createAuthService(keycloakConfig);
|
|
167
|
-
|
|
168
|
-
// Direct login without external redirect
|
|
169
|
-
try {
|
|
170
|
-
await authService.login({
|
|
171
|
-
credentials: {
|
|
172
|
-
username: "internal.user@company.com",
|
|
173
|
-
password: "userPassword123",
|
|
174
|
-
},
|
|
175
|
-
});
|
|
176
|
-
console.log("User logged in successfully!");
|
|
177
|
-
} catch (error) {
|
|
178
|
-
if (error instanceof DirectLoginError) {
|
|
179
|
-
console.error("Direct login failed:", error.message);
|
|
180
|
-
// Handle specific direct login errors:
|
|
181
|
-
// - Invalid credentials
|
|
182
|
-
// - Account locked
|
|
183
|
-
// - Client not configured for direct access
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
**📋 Keycloak Configuration Requirements for Direct Login:**
|
|
99
|
+
class SerOAuth {
|
|
100
|
+
constructor(config: SerOAuthConfig);
|
|
189
101
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
102
|
+
// Métodos principais
|
|
103
|
+
async init(options?: InitOptions): Promise<boolean>;
|
|
104
|
+
async login(options?: LoginOptions): Promise<void>;
|
|
105
|
+
async logout(options?: LogoutOptions): Promise<void>;
|
|
106
|
+
async updateToken(minValidity?: number): Promise<boolean>;
|
|
194
107
|
|
|
195
|
-
|
|
108
|
+
// Propriedades
|
|
109
|
+
get authenticated(): boolean;
|
|
110
|
+
get token(): string | null;
|
|
111
|
+
get refreshToken(): string | null;
|
|
112
|
+
get idToken(): string | null;
|
|
196
113
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
) {
|
|
204
|
-
try {
|
|
205
|
-
if (isInternalUser && credentials) {
|
|
206
|
-
// Direct login for internal users
|
|
207
|
-
await authService.login({ credentials });
|
|
208
|
-
} else {
|
|
209
|
-
// External redirect for external users
|
|
210
|
-
await authService.login();
|
|
211
|
-
}
|
|
212
|
-
} catch (error) {
|
|
213
|
-
console.error("Login failed:", error);
|
|
214
|
-
}
|
|
114
|
+
// Callbacks
|
|
115
|
+
onAuthSuccess?: () => void;
|
|
116
|
+
onAuthError?: (err: unknown) => void;
|
|
117
|
+
onAuthLogout?: () => void;
|
|
118
|
+
onTokenExpired?: () => void;
|
|
119
|
+
onTokenRefreshed?: () => void;
|
|
215
120
|
}
|
|
216
121
|
```
|
|
217
122
|
|
|
218
|
-
###
|
|
123
|
+
### Configuração
|
|
219
124
|
|
|
220
125
|
```typescript
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
const authService = await createAuthService({
|
|
228
|
-
url: "https://your-keycloak-server",
|
|
229
|
-
realm: "your-realm",
|
|
230
|
-
clientId: "your-client-id",
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
// Check authentication state
|
|
234
|
-
const authState = getAuthState(authService);
|
|
235
|
-
console.log("Is authenticated:", authState.isAuthenticated);
|
|
236
|
-
|
|
237
|
-
// Login (external redirect)
|
|
238
|
-
if (!authState.isAuthenticated) {
|
|
239
|
-
await authService.login();
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// Direct login for internal users (no external redirect)
|
|
243
|
-
if (!authState.isAuthenticated) {
|
|
244
|
-
await authService.login({
|
|
245
|
-
credentials: {
|
|
246
|
-
username: "internal.user@company.com",
|
|
247
|
-
password: "userPassword123",
|
|
248
|
-
},
|
|
249
|
-
});
|
|
250
|
-
}
|
|
126
|
+
type SerOAuthConfig = {
|
|
127
|
+
url: string; // https://seu-keycloak.com
|
|
128
|
+
realm: string; // nome-do-realm
|
|
129
|
+
clientId: string; // seu-client-id
|
|
130
|
+
idp?: string; // hint para IDP específico
|
|
131
|
+
};
|
|
251
132
|
|
|
252
|
-
|
|
253
|
-
|
|
133
|
+
type InitOptions = {
|
|
134
|
+
onLoad?: "check-sso" | "login-required";
|
|
135
|
+
silentCheckSsoRedirectUri?: string;
|
|
136
|
+
pkceMethod?: "S256";
|
|
137
|
+
};
|
|
254
138
|
```
|
|
255
139
|
|
|
256
|
-
###
|
|
140
|
+
### Store (Zustand)
|
|
257
141
|
|
|
258
142
|
```typescript
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
143
|
+
const authState = useAuthStore();
|
|
144
|
+
// {
|
|
145
|
+
// accessToken: string | null
|
|
146
|
+
// refreshToken: string | null
|
|
147
|
+
// idToken: string | null
|
|
148
|
+
// accessExpiresAt: number | null
|
|
149
|
+
// authenticated: boolean
|
|
150
|
+
// setTokens: (tokens: TokenSet) => void
|
|
151
|
+
// clear: () => void
|
|
152
|
+
// }
|
|
268
153
|
```
|
|
269
154
|
|
|
270
|
-
##
|
|
155
|
+
## Migração do keycloak-js
|
|
271
156
|
|
|
272
|
-
###
|
|
157
|
+
### Antes (keycloak-js)
|
|
273
158
|
|
|
274
159
|
```typescript
|
|
275
|
-
import
|
|
276
|
-
isTokenExpired,
|
|
277
|
-
parseTokenUserInfo,
|
|
278
|
-
hasRole,
|
|
279
|
-
getUserRoles,
|
|
280
|
-
} from "@elogroup-sereduc/ser-front-core-client";
|
|
160
|
+
import Keycloak from "keycloak-js";
|
|
281
161
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
162
|
+
const keycloak = new Keycloak({
|
|
163
|
+
url: "https://keycloak.com",
|
|
164
|
+
realm: "myrealm",
|
|
165
|
+
clientId: "myclient",
|
|
166
|
+
});
|
|
287
167
|
|
|
288
|
-
|
|
289
|
-
const isAdmin = hasRole(token, "admin");
|
|
290
|
-
const userRoles = getUserRoles(token);
|
|
168
|
+
await keycloak.init({ onLoad: "check-sso" });
|
|
291
169
|
```
|
|
292
170
|
|
|
293
|
-
###
|
|
171
|
+
### Depois (ser-auth)
|
|
294
172
|
|
|
295
173
|
```typescript
|
|
296
174
|
import {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
redirectToLogin,
|
|
175
|
+
createSerOAuth,
|
|
176
|
+
initAuth,
|
|
300
177
|
} from "@elogroup-sereduc/ser-front-core-client";
|
|
301
178
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
// Result: 'https://domain.com/backoffice/'
|
|
308
|
-
|
|
309
|
-
// Use with auth functions
|
|
310
|
-
const keycloakService = getKeycloakService(apiClient);
|
|
311
|
-
|
|
312
|
-
// Logout with base path
|
|
313
|
-
await logout(keycloakService, undefined, "/portal-aluno");
|
|
179
|
+
const kc = createSerOAuth({
|
|
180
|
+
url: "https://keycloak.com",
|
|
181
|
+
realm: "myrealm",
|
|
182
|
+
clientId: "myclient",
|
|
183
|
+
});
|
|
314
184
|
|
|
315
|
-
|
|
316
|
-
redirectToLogin(undefined, "/portal-aluno");
|
|
185
|
+
await initAuth(kc);
|
|
317
186
|
```
|
|
318
187
|
|
|
319
|
-
##
|
|
320
|
-
|
|
321
|
-
### Default Behavior
|
|
322
|
-
|
|
323
|
-
By default, when token refresh fails, the user is redirected to the login page.
|
|
188
|
+
## Exemplos Avançados
|
|
324
189
|
|
|
325
190
|
### Custom Error Handling
|
|
326
191
|
|
|
327
192
|
```typescript
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
api: {
|
|
333
|
-
baseURL: "https://api.example.com",
|
|
334
|
-
onTokenRefreshFailed: (error) => {
|
|
335
|
-
console.error("Auth failed:", error);
|
|
336
|
-
// Custom handling - show modal, redirect to specific page, etc.
|
|
337
|
-
showAuthErrorModal();
|
|
338
|
-
},
|
|
339
|
-
},
|
|
340
|
-
});
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
## Silent SSO Setup
|
|
344
|
-
|
|
345
|
-
For silent SSO, create a `silent-check-sso.html` file in your public folder:
|
|
346
|
-
|
|
347
|
-
```html
|
|
348
|
-
<!doctype html>
|
|
349
|
-
<html>
|
|
350
|
-
<body>
|
|
351
|
-
<script>
|
|
352
|
-
parent.postMessage(location.href, location.origin);
|
|
353
|
-
</script>
|
|
354
|
-
</body>
|
|
355
|
-
</html>
|
|
356
|
-
```
|
|
357
|
-
|
|
358
|
-
Then configure your client:
|
|
193
|
+
kc.onAuthError = (error) => {
|
|
194
|
+
console.error("Auth error:", error);
|
|
195
|
+
// Redirecionar para página de erro
|
|
196
|
+
};
|
|
359
197
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
keycloak: {
|
|
363
|
-
url: "https://your-keycloak-server",
|
|
364
|
-
realm: "your-realm",
|
|
365
|
-
clientId: "your-client-id",
|
|
366
|
-
initOptions: {
|
|
367
|
-
onLoad: "check-sso",
|
|
368
|
-
silentCheckSsoRedirectUri: `${window.location.origin}/silent-check-sso.html`,
|
|
369
|
-
},
|
|
370
|
-
},
|
|
371
|
-
// ...
|
|
198
|
+
kc.onTokenExpired = () => {
|
|
199
|
+
console.log("Token expirado, renovando...");
|
|
372
200
|
};
|
|
373
201
|
```
|
|
374
202
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
Full TypeScript support with comprehensive type definitions:
|
|
203
|
+
### Múltiplas Instâncias
|
|
378
204
|
|
|
379
205
|
```typescript
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
DirectLoginCredentials,
|
|
386
|
-
AuthenticationError,
|
|
387
|
-
TokenRefreshError,
|
|
388
|
-
DirectLoginError,
|
|
389
|
-
} from "@elogroup-sereduc/ser-front-core-client";
|
|
390
|
-
```
|
|
206
|
+
const adminKc = createSerOAuth({
|
|
207
|
+
url: "https://admin-sso.com",
|
|
208
|
+
realm: "admin",
|
|
209
|
+
clientId: "admin-client",
|
|
210
|
+
});
|
|
391
211
|
|
|
392
|
-
|
|
212
|
+
const userKc = createSerOAuth({
|
|
213
|
+
url: "https://user-sso.com",
|
|
214
|
+
realm: "users",
|
|
215
|
+
clientId: "user-client",
|
|
216
|
+
});
|
|
217
|
+
```
|
|
393
218
|
|
|
394
|
-
|
|
395
|
-
- ✅ **Proactive refresh**: Uses `updateToken(30)` before requests instead of 401/403 retry
|
|
396
|
-
- ✅ **Keycloak integration**: OIDC-based authentication instead of session-based
|
|
397
|
-
- ✅ **Per-client config**: Keycloak config provided per API client
|
|
398
|
-
- ✅ **No retry logic**: Does not retry requests on auth failure
|
|
399
|
-
- ✅ **Direct login support**: Internal users can login with username/password without external redirect
|
|
400
|
-
- ✅ **Base path support**: Applications running in subfolders (e.g., /portal-aluno, /backoffice) are fully supported
|
|
401
|
-
- ✅ **Mixed authentication**: Supports both internal (direct) and external (redirect) users in the same app
|
|
219
|
+
### Interceptação Customizada
|
|
402
220
|
|
|
403
|
-
|
|
221
|
+
```typescript
|
|
222
|
+
const api = createApiClient(kc);
|
|
404
223
|
|
|
405
|
-
|
|
224
|
+
api.interceptors.request.use((config) => {
|
|
225
|
+
// Adicionar headers customizados
|
|
226
|
+
config.headers["X-Custom-Header"] = "value";
|
|
227
|
+
return config;
|
|
228
|
+
});
|
|
229
|
+
```
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type AxiosInstance } from "axios";
|
|
2
2
|
import { KeycloakService } from "./keycloak.js";
|
|
3
|
-
import type { CoreClientConfig
|
|
3
|
+
import type { CoreClientConfig } from "./types/index.js";
|
|
4
4
|
export declare function createApiClient(config: CoreClientConfig): AxiosInstance;
|
|
5
|
-
export declare function createSimpleApiClient(
|
|
5
|
+
export declare function createSimpleApiClient(config: CoreClientConfig): AxiosInstance;
|
|
6
6
|
export declare function getKeycloakService(apiClient: AxiosInstance): KeycloakService | undefined;
|
|
7
|
-
//# sourceMappingURL=
|
|
7
|
+
//# sourceMappingURL=api-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA,OAAc,EACZ,KAAK,aAAa,EAGnB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAmB,MAAM,kBAAkB,CAAC;AAM1E,wBAAgB,eAAe,CAAC,MAAM,EAAE,gBAAgB,GAAG,aAAa,CA8EvE;AAyBD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,gBAAgB,GAAG,aAAa,CAE7E;AAKD,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,aAAa,GACvB,eAAe,GAAG,SAAS,CAE7B"}
|