webba-id-sdk
v2.0.2
Published
SDK officiel pour intégrer l'authentification Webba ID dans vos applications
Downloads
356
Maintainers
Readme
webba-id-sdk
SDK officiel pour intégrer l'authentification Webba ID dans vos applications.
Installation
npm install webba-id-sdkFonctionnalités
- OAuth 2.0 Authorization Code Flow
- PKCE (Proof Key for Code Exchange) pour les SPAs
- Protection CSRF avec paramètre state
- Refresh tokens avec rotation automatique
- Révocation de tokens
- Hook React inclus
Utilisation rapide
Côté Client (SPA)
import { createWebbaID } from 'webba-id-sdk'
const webbaId = createWebbaID({
appKey: 'wba_votre_app_key',
redirectUri: 'https://votre-app.com/auth/callback',
usePKCE: true // Recommandé pour les SPAs
})
// Rediriger vers la page de connexion
await webbaId.login()Côté Serveur
import { createWebbaID } from 'webba-id-sdk'
const webbaId = createWebbaID({
appKey: process.env.WEBBA_APP_KEY!,
appSecret: process.env.WEBBA_APP_SECRET!,
redirectUri: process.env.APP_URL + '/auth/callback'
})
// Échanger le code contre des tokens
const tokens = await webbaId.exchangeCode(code, codeVerifier)
// Récupérer les infos utilisateur
const user = await webbaId.getUserInfo(tokens.access_token)PKCE (Recommandé pour les SPAs)
PKCE protège contre les attaques d'interception de code d'autorisation.
const webbaId = createWebbaID({
appKey: 'wba_xxx',
redirectUri: '/auth/callback',
usePKCE: true
})
// login() génère et stocke automatiquement le code_verifier
await webbaId.login()
// Sur la page de callback
const { code, state } = webbaId.getAuthorizationParams()
const codeVerifier = webbaId.getStoredCodeVerifier()
// Envoyer code + codeVerifier au backend
await fetch('/api/auth/callback', {
method: 'POST',
body: JSON.stringify({ code, codeVerifier })
})Protection CSRF (State)
Le SDK génère et vérifie automatiquement le paramètre state.
// Le state est généré automatiquement
await webbaId.login()
// Sur la page de callback
const { code, state, error } = webbaId.getAuthorizationParams()
// Vérifier le state
if (!webbaId.verifyState(state)) {
console.error('State invalide - possible attaque CSRF')
return
}Refresh Tokens
Les access_tokens expirent après 1 heure. Utilisez le refresh_token pour les renouveler.
// Côté serveur
try {
const newTokens = await webbaId.refreshToken(refreshToken)
// IMPORTANT: Le refresh_token est à usage unique (rotation)
// Stockez toujours le nouveau refresh_token
saveTokens(newTokens)
} catch (error) {
// Refresh token expiré ou révoqué
// Rediriger vers la page de connexion
}Déconnexion
Révoquez les tokens lors de la déconnexion.
// Déconnexion complète (révoque access + refresh tokens)
await webbaId.logout(accessToken, refreshToken)
// Ou révoquer un token spécifique
await webbaId.revokeToken(accessToken)Hook React
import { useWebbaID } from 'webba-id-sdk'
function LoginButton() {
const { login } = useWebbaID({
appKey: 'wba_xxx',
redirectUri: '/auth/callback',
usePKCE: true
})
return (
<button onClick={login}>
Se connecter avec Webba ID
</button>
)
}
function AuthCallback() {
const { getAuthorizationParams, verifyState, getCodeVerifier } = useWebbaID({
appKey: 'wba_xxx',
redirectUri: '/auth/callback',
usePKCE: true
})
useEffect(() => {
const { code, state, error } = getAuthorizationParams()
if (error || !verifyState(state)) {
// Gérer l'erreur
return
}
const codeVerifier = getCodeVerifier()
// Envoyer au backend...
}, [])
return <div>Connexion en cours...</div>
}API Reference
Configuration
| Option | Type | Requis | Description |
|--------|------|--------|-------------|
| appKey | string | Oui | Clé publique de l'application (wba_xxx) |
| appSecret | string | Serveur | Clé secrète (côté serveur uniquement) |
| redirectUri | string | Oui | URL de callback après authentification |
| usePKCE | boolean | Non | Active PKCE pour les SPAs (défaut: false) |
| baseUrl | string | Non | URL de base Webba ID |
| apiUrl | string | Non | URL de l'API Webba ID |
Méthodes
| Méthode | Description | Environnement |
|---------|-------------|---------------|
| login() | Redirige vers la page de connexion (async, gère PKCE/state) | Client |
| getLoginUrl(state?, codeChallenge?) | Retourne l'URL de connexion | Client/Serveur |
| getAuthorizationParams() | Récupère code, state, error depuis l'URL | Client |
| verifyState(state) | Vérifie le state CSRF | Client |
| getStoredCodeVerifier() | Récupère le code_verifier PKCE stocké | Client |
| exchangeCode(code, codeVerifier?) | Échange un code contre des tokens | Serveur |
| refreshToken(refreshToken) | Rafraîchit l'access_token | Client/Serveur |
| revokeToken(token) | Révoque un token | Client/Serveur |
| logout(accessToken, refreshToken?) | Révoque tous les tokens | Client/Serveur |
| getUserInfo(token) | Récupère les infos utilisateur | Client/Serveur |
| getProfile(token) | Récupère le profil complet | Client/Serveur |
| updateProfile(token, data) | Met à jour le profil | Client/Serveur |
| verifyToken(token) | Vérifie si un token est valide | Client/Serveur |
Types
interface TokenResponse {
access_token: string
refresh_token: string
token_type: string
expires_in: number
expires_at: string
user_id: string
}
interface AuthorizationParams {
code: string | null
state: string | null
error?: string | null
error_description?: string | null
}
interface WebbaIDUser {
user_id: string
email: string
app_id?: string
profile?: UserProfile
subscriptions?: Subscription[]
}
interface FullProfile {
user_id: string
email?: string
email_verified?: boolean
profile: UserProfile
subscriptions: Subscription[]
roles: UserRole[]
}Exemple complet
Variables d'environnement
# Client (.env)
VITE_WEBBA_APP_KEY=wba_xxx
VITE_APP_URL=https://votre-app.com
# Serveur (.env)
WEBBA_APP_KEY=wba_xxx
WEBBA_APP_SECRET=wbs_xxx
APP_URL=https://votre-app.comFrontend (React)
// src/pages/Login.tsx
import { useWebbaID } from 'webba-id-sdk'
export function Login() {
const { login } = useWebbaID({
appKey: import.meta.env.VITE_WEBBA_APP_KEY,
redirectUri: import.meta.env.VITE_APP_URL + '/auth/callback',
usePKCE: true
})
return (
<button onClick={login}>
Se connecter avec Webba ID
</button>
)
}
// src/pages/AuthCallback.tsx
import { useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { useWebbaID } from 'webba-id-sdk'
export function AuthCallback() {
const navigate = useNavigate()
const { getAuthorizationParams, verifyState, getCodeVerifier } = useWebbaID({
appKey: import.meta.env.VITE_WEBBA_APP_KEY,
redirectUri: import.meta.env.VITE_APP_URL + '/auth/callback',
usePKCE: true
})
useEffect(() => {
const { code, state, error } = getAuthorizationParams()
if (error) {
navigate('/login?error=' + error)
return
}
if (!verifyState(state)) {
navigate('/login?error=invalid_state')
return
}
const codeVerifier = getCodeVerifier()
fetch('/api/auth/callback', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ code, codeVerifier })
})
.then(res => res.ok ? navigate('/dashboard') : navigate('/login?error=auth_failed'))
.catch(() => navigate('/login?error=network_error'))
}, [])
return <div>Connexion en cours...</div>
}Backend (Express)
// server/auth.ts
import { createWebbaID } from 'webba-id-sdk'
import express from 'express'
const app = express()
const webbaId = createWebbaID({
appKey: process.env.WEBBA_APP_KEY!,
appSecret: process.env.WEBBA_APP_SECRET!,
redirectUri: process.env.APP_URL + '/auth/callback'
})
// Callback d'authentification
app.post('/api/auth/callback', async (req, res) => {
const { code, codeVerifier } = req.body
try {
const tokens = await webbaId.exchangeCode(code, codeVerifier)
const user = await webbaId.getUserInfo(tokens.access_token)
// Sauvegarder en session/cookie
req.session.accessToken = tokens.access_token
req.session.refreshToken = tokens.refresh_token
req.session.userId = user.user_id
res.json({ success: true })
} catch (error) {
res.status(401).json({ error: 'Authentication failed' })
}
})
// Middleware pour rafraîchir le token si expiré
app.use(async (req, res, next) => {
if (!req.session.accessToken) return next()
const { valid } = await webbaId.verifyToken(req.session.accessToken)
if (!valid && req.session.refreshToken) {
try {
const newTokens = await webbaId.refreshToken(req.session.refreshToken)
req.session.accessToken = newTokens.access_token
req.session.refreshToken = newTokens.refresh_token
} catch {
// Refresh échoué, déconnecter
req.session.destroy()
return res.status(401).json({ error: 'Session expired' })
}
}
next()
})
// Déconnexion
app.post('/api/auth/logout', async (req, res) => {
const { accessToken, refreshToken } = req.session
if (accessToken) {
await webbaId.logout(accessToken, refreshToken)
}
req.session.destroy()
res.json({ success: true })
})Migration v1 vers v2
Breaking changes
login()est maintenant async// v1 webbaId.login() // v2 await webbaId.login()getCodeFromUrl()est déprécié, utilisezgetAuthorizationParams()// v1 const code = webbaId.getCodeFromUrl() // v2 const { code, state, error } = webbaId.getAuthorizationParams()exchangeCode()retourne maintenant aussirefresh_token// v1 const { access_token, user_id } = await webbaId.exchangeCode(code) // v2 const { access_token, refresh_token, user_id } = await webbaId.exchangeCode(code, codeVerifier)
Nouvelles fonctionnalités
usePKCE: truedans la config pour activer PKCEverifyState(state)pour la protection CSRFgetStoredCodeVerifier()pour récupérer le code_verifier PKCErefreshToken(token)pour rafraîchir les tokensrevokeToken(token)pour révoquer un tokenlogout(accessToken, refreshToken?)pour la déconnexion
Licence
MIT - Webba Creative Technologies
