Prompt utilisé pour régénérer cette page :
Page: Authentication - Google OAuth2 Management
Title: "Authentication"
Description: "Google OAuth2 authentication via API"
Icon: shield-account
Tags: auth, google, oauth2
Features: Google OAuth2, Token management, Session persistence, RBAC (Role & Permissions)
Category: internal
Front matter: no js/scss keys (uses default convention)
HTML structure in index.md (pure HTML, NO canvas):
<div id="auth-container">
<!-- Section 1: Auth Status -->
<div id="auth-status">
<div id="auth-loading">Loading...</div>
<div id="auth-signed-out" class="hidden">
<p>Sign in to access protected features.</p>
<button id="btn-signin" class="button color-primary">Sign in with Google</button>
</div>
<div id="auth-signed-in" class="hidden">
div.user-profile: <img id="user-avatar" class="avatar"> + div.user-info (span#user-name.name, span#user-email.email, span#user-role.role.badge)
div.auth-actions: <button id="btn-refresh" class="button small">Refresh</button> + <button id="btn-signout" class="button color-danger">Sign Out</button>
</div>
</div>
<!-- Section 2: Token Info (hidden) -->
<div id="token-info" class="hidden">
<h3>Token Info</h3>
<dl>: Expires (#token-expires "-"), Status (#token-status "-")
div.token-display: <label for="token-value">JWT Token</label> + <textarea id="token-value" readonly rows="4">
div.token-actions: <button id="btn-copy-token" class="button small">Copy Token</button> + <button id="btn-test-api" class="button small color-info">Test /auth/me</button>
<pre id="api-result" class="hidden"> (populated by JS with API response)
</div>
<!-- Section 3: Permissions (hidden) -->
<div id="permissions-info" class="hidden">
<h3>Permissions</h3>
<ul id="permissions-list"> (populated by JS)
</div>
</div>
No widget files — all content is in index.md.
Architecture (1 JS file):
default.js — ES module, top-level code (NOT IIFE), ~226 lines:
Import: auth from /_lib/auth_v1.js (shared auth library)
API_URL: 'https://api.cylian.org'
DOM elements cache: loadingEl, signedOutEl, signedInEl, userAvatar, userName, userEmail, userRole,
btnSignin, btnSignout, btnRefresh, tokenInfo, tokenExpires, tokenStatus, btnCopyToken,
btnTestApi, apiResult, tokenValue, permissionsInfo, permissionsList
formatExpiry(timestamp): Converts Unix timestamp (seconds) to locale string. Returns '-' if falsy
updateUI(): Toggles visibility of 3 states via .hidden class:
Signed in: shows signed-in div, token-info, permissions-info. Populates:
Avatar (user.picture), name, email, role badge
Token expiry (formatExpiry(auth.getExpiry())), status "Valid" with .status-valid class
Token textarea value (auth.getToken())
Permissions list (user.permissions array → <li> elements, or "No permissions" if empty)
Signed out: shows signed-out div, hides token/permissions/api-result
handleSignIn(user): Logs email, calls updateUI
handleSignOut(): Logs sign-out, calls updateUI
copyToken(): Async. Gets auth.getToken(), copies to clipboard via navigator.clipboard.writeText.
Shows "Copied!" feedback for 2000ms then reverts to "Copy Token"
testApi(): Async. Fetches GET ${API_URL}/@auth/me with auth.getAuthHeaders() + Content-Type JSON.
Displays JSON.stringify(data, null, 2) in #api-result pre element
refreshUser(): Async. Disables button, shows "Refreshing...", calls auth.refreshUser(), updates UI
init(): Async.
1. auth.configure({ apiUrl: API_URL, onSignIn: handleSignIn, onSignOut: handleSignOut })
2. Binds: btn-signin → auth.signIn(), btn-signout → auth.signOut(), btn-refresh → refreshUser,
btn-copy-token → copyToken, btn-test-api → testApi
3. await auth.init() (restores session, checks OAuth callback)
4. updateUI()
Auth module API (/_lib/auth_v1.js) used:
auth.configure({apiUrl, onSignIn, onSignOut})
auth.init() — restores session, checks OAuth callback URL
auth.isSignedIn() — returns boolean
auth.getUser() — returns {name, email, picture, role, permissions[]}
auth.getToken() — returns JWT string
auth.getExpiry() — returns Unix timestamp (seconds)
auth.getAuthHeaders() — returns {Authorization: 'Bearer ...'} headers object
auth.signIn() — initiates Google OAuth2 flow
auth.signOut() — clears session
auth.refreshUser() — refreshes user data from API
Entry point: init() called immediately (top-level await)
default.scss:
#auth-container: max-width 480px, margin 0 auto
#auth-status: padding var(--layout-spacing), background var(--background-color-secondary), border-radius, margin-bottom
.hidden: display none !important
.user-profile: flex row, center, gap layout-spacing, margin-bottom
.avatar: 64px circle, 2px border
.user-info: flex column, 0.25rem gap
.name: bold, 1.1rem. .email: secondary color, 0.9rem
.auth-actions: flex row, gap layout-spacing
#token-info: padding, bg secondary, border-radius
h3: no top margin. dl: grid (auto 1fr), gap 0.5rem 1rem
dt: bold, secondary color. dd: margin 0
.token-actions: flex row, 0.5rem gap, margin-bottom
.status-valid: color var(--color-success). .status-expired: color var(--color-danger)
#api-result: bg base, 1px border, border-radius, padding, 0.85rem font, overflow-x auto, max-height 300px
.error: danger color, 10% danger bg, border-radius, padding
Important implementation notes:
- NO canvas — pure HTML/CSS authentication management page
- All HTML structure defined in index.md, not JS-generated
- Uses shared auth library (/_lib/auth_v1.js) for all OAuth2 logic
- API endpoint: https://api.cylian.org
- Authentication test endpoint: /@auth/me
- Token displayed in readonly textarea for easy copy
- 3 visibility states managed via .hidden class: loading → signed-out or signed-in
- Role displayed as badge, permissions as list items
- No animation loop — event-driven only
- No widget files — everything is in index.md
- Page auto-initializes (top-level init() call, not DOMContentLoaded)
Page entièrement générée et maintenue par IA, sans intervention humaine.