@elogroup-sereduc/ser-front-core-client
v4.0.0
Published
Complete OAuth/OIDC authentication system with Silent SSO, PKCE, and API client for Ser Educacional applications
Readme
Ser Auth Library
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.
Características
- ✅ Silent SSO: Autenticação invisível via iframe
- ✅ PKCE S256: Segurança para SPAs (Single Page Applications)
- ✅ Token Refresh: Renovação automática de tokens
- ✅ API Client: Cliente HTTP com interceptadores automáticos
- ✅ Route Guards: Proteção de rotas para frameworks como TanStack Router
- ✅ Zustand Store: Gerenciamento de estado em memória
- ✅ IDP Hint: Suporte a redirecionamento automático para provedores específicos
Instalação
npm install @elogroup-sereduc/ser-front-core-clientSetup Básico
1. Configuração Inicial
import {
createKeycloakAuthFromUrl,
initAuth,
} from "@elogroup-sereduc/ser-front-core-client";
// Criar instância do SerOAuth
const kc = createKeycloakAuthFromUrl(
"https://seu-keycloak.com/realms/seu-realm/protocol/openid-connect/auth",
"seu-client-id",
"seu-idp-hint", // opcional
);
// Inicializar autenticação
const authenticated = await initAuth(kc, "/seu-base-path");2. Arquivo Silent-Check-SSO
Copie o arquivo public/silent-check-sso.html para a pasta public da sua aplicação.
3. Context de Autenticação (React)
import { useAuthStore } from '@elogroup-sereduc/ser-front-core-client'
export function AuthContext({ children }) {
const authState = useAuthStore()
return (
<AuthProvider value={{
authenticated: authState.authenticated,
user: extractUserFromToken(authState.idToken),
login: () => kc.login(),
logout: () => kc.logout(),
}}>
{children}
</AuthProvider>
)
}4. Cliente API
import { createApiClient } from "@elogroup-sereduc/ser-front-core-client";
const api = createApiClient(kc, "https://sua-api.com");
// O cliente automaticamente:
// - Adiciona Bearer token nos headers
// - Renova token em caso de 401
// - Retenta requisição com novo token5. Route Guards
import { createAuthGuard } from "@elogroup-sereduc/ser-front-core-client";
import { createFileRoute } from "@tanstack/react-router";
const requireAuth = createAuthGuard(kc);
export const Route = createFileRoute("/protected")({
beforeLoad: requireAuth,
component: ProtectedComponent,
});API Reference
SerOAuth
class SerOAuth {
constructor(config: SerOAuthConfig);
// Métodos principais
async init(options?: InitOptions): Promise<boolean>;
async login(options?: LoginOptions): Promise<void>;
async logout(options?: LogoutOptions): Promise<void>;
async updateToken(minValidity?: number): Promise<boolean>;
// Propriedades
get authenticated(): boolean;
get token(): string | null;
get refreshToken(): string | null;
get idToken(): string | null;
// Callbacks
onAuthSuccess?: () => void;
onAuthError?: (err: unknown) => void;
onAuthLogout?: () => void;
onTokenExpired?: () => void;
onTokenRefreshed?: () => void;
}Configuração
type SerOAuthConfig = {
url: string; // https://seu-keycloak.com
realm: string; // nome-do-realm
clientId: string; // seu-client-id
idp?: string; // hint para IDP específico
};
type InitOptions = {
onLoad?: "check-sso" | "login-required";
silentCheckSsoRedirectUri?: string;
pkceMethod?: "S256";
};Store (Zustand)
const authState = useAuthStore();
// {
// accessToken: string | null
// refreshToken: string | null
// idToken: string | null
// accessExpiresAt: number | null
// authenticated: boolean
// setTokens: (tokens: TokenSet) => void
// clear: () => void
// }Migração do keycloak-js
Antes (keycloak-js)
import Keycloak from "keycloak-js";
const keycloak = new Keycloak({
url: "https://keycloak.com",
realm: "myrealm",
clientId: "myclient",
});
await keycloak.init({ onLoad: "check-sso" });Depois (ser-auth)
import {
createSerOAuth,
initAuth,
} from "@elogroup-sereduc/ser-front-core-client";
const kc = createSerOAuth({
url: "https://keycloak.com",
realm: "myrealm",
clientId: "myclient",
});
await initAuth(kc);Exemplos Avançados
Custom Error Handling
kc.onAuthError = (error) => {
console.error("Auth error:", error);
// Redirecionar para página de erro
};
kc.onTokenExpired = () => {
console.log("Token expirado, renovando...");
};Múltiplas Instâncias
const adminKc = createSerOAuth({
url: "https://admin-sso.com",
realm: "admin",
clientId: "admin-client",
});
const userKc = createSerOAuth({
url: "https://user-sso.com",
realm: "users",
clientId: "user-client",
});Interceptação Customizada
const api = createApiClient(kc);
api.interceptors.request.use((config) => {
// Adicionar headers customizados
config.headers["X-Custom-Header"] = "value";
return config;
});