@hgdc/auth 0.5.0 → 0.6.1

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 CHANGED
@@ -1,13 +1,13 @@
1
1
  # @hgdc/auth
2
2
 
3
- Connexion d'un produit HGDC à HGDC Account (OIDC) : bouton « Se connecter avec HGDC », configuration du client better-auth, proxy `/api/auth` pour TanStack Start et gardes Convex.
3
+ Connexion d'un produit de la famille à Account (OIDC) : bouton « Se connecter avec H family », configuration du client better-auth, proxy `/api/auth` pour TanStack Start et gardes Convex.
4
4
 
5
5
  | Import | Contenu |
6
6
  | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
7
7
  | `@hgdc/auth` | `HGDC_ISSUER`, `HGDC_PROVIDER_ID`, `HGDC_SCOPES`, entrée commune (`HGDC_ENTRY_PATH`, `safeNextPath`, `hgdcEntryUrl`), rôles (`highestRole`, `hasRole`), `parseHgdcProfile`, `verifiedOrganizationsFromIdToken`, `verifyHgdcIdToken`, `planOrganizationSync`, fraîcheur (`membershipIsFresh`, `SESSION_TTL_SECONDS`, `MEMBERSHIP_TTL_MS`, `KEY_MEMBERSHIP_TTL_MS`) |
8
8
  | `@hgdc/auth/server` | `hgdcProvider` (plugin `genericOAuth`), `createAuthProxy`, `restoreFetchMode`, `createHgdcEntry` |
9
9
  | `@hgdc/auth/convex` | `requireIdentity`, `requireOrgMember`, `isAuthError`, `authErrorReason`, `AUTH_ERROR_MESSAGES` |
10
- | `@hgdc/auth/react` | `HgdcSignInButton`, `startHgdcSignIn`, `HgdcMark` |
10
+ | `@hgdc/auth/react` | `HgdcSignInButton`, `startHgdcSignIn`, `HgdcMark` (le H tricolore de la famille, `HGDC_MARK_SVG`) |
11
11
 
12
12
  Pairs : better-auth 1.6, convex 1.46+, React 19 (chacun facultatif selon l'import).
13
13
 
@@ -55,6 +55,31 @@ authComponent.registerRoutes(http, (ctx) => {
55
55
  })
56
56
  ```
57
57
 
58
+ ## Clés JWKS statiques côté Convex
59
+
60
+ Chaque appel HTTP à Convex avec un jeton (le rendu serveur de TanStack Start, `fetchAuthQuery`) fait vérifier ce jeton par le backend Convex, qui ne le met jamais en cache. Avec `getAuthConfigProvider()` seul, il va chercher les clés à `<site>/api/auth/convex/jwks` **à chaque appel** : sous charge, cette adresse répond 429 et la page tombe en erreur. Les clés se donnent donc en dur, par la variable `JWKS` du déploiement Convex :
61
+
62
+ ```ts
63
+ // convex/auth.config.ts
64
+ export default { providers: [getAuthConfigProvider({ jwks: process.env.JWKS })] } satisfies AuthConfig
65
+
66
+ // convex/auth.ts, dans les plugins
67
+ convex({ authConfig, jwks: process.env.JWKS })
68
+
69
+ // convex/authKeys.ts
70
+ export const latestJwks = internalAction({
71
+ args: {},
72
+ handler: async (ctx) => await createAuth(ctx).api.getLatestJwks(),
73
+ })
74
+ ```
75
+
76
+ ```sh
77
+ npx convex run authKeys:latestJwks --prod | npx convex env set JWKS --prod
78
+ npx convex deploy
79
+ ```
80
+
81
+ Sans `JWKS`, la configuration retombe sur l'adresse : un déploiement de développement marche sans rien poser. La variable contient la clé privée chiffrée : elle ne sort jamais du déploiement (ni affichée, ni copiée ailleurs). Après une rotation des clés, relancer les deux commandes.
82
+
58
83
  ## Entrée commune `/auth/hgdc`
59
84
 
60
85
  Le menu « Produits » (`@hgdc/ui/account-menu`) envoie vers `https://<mot>.hgdc.ch/auth/hgdc`, pas vers la page d'accueil publique. Chaque produit monte cette route serveur, au même chemin :
package/dist/react.d.ts CHANGED
@@ -35,12 +35,20 @@ export declare function startHgdcSignIn(authClient: HgdcAuthClient, { callbackUR
35
35
  ok: false;
36
36
  error: unknown;
37
37
  }>;
38
- /** Monogramme HGDC, en `currentColor`. */
39
- export declare function HgdcMark(props: {
38
+ /**
39
+ * Le H tricolore de la famille, copie exacte de `@hgdc/ui/family/hfamily-icon.svg` (un test le
40
+ * vérifie) : `@hgdc/auth` ne dépend pas de `@hgdc/ui`.
41
+ */
42
+ export declare const HGDC_MARK_SVG: string;
43
+ /**
44
+ * Le H tricolore de la famille, en image : ses dégradés gardent leurs identifiants pour eux, deux
45
+ * marques dans une page ne se marchent pas dessus. Couleurs pleines, jamais recolorées.
46
+ */
47
+ export declare function HgdcMark({ className }: {
40
48
  className?: string;
41
49
  }): ReactElement;
42
50
  /**
43
- * Bouton « Se connecter avec HGDC ». Sans style propre : le produit le met en forme par
51
+ * Bouton « Se connecter avec H family ». Sans style propre : le produit le met en forme par
44
52
  * `className`, l'état d'attente est exposé par `aria-busy` et `data-pending`.
45
53
  */
46
54
  export declare function HgdcSignInButton({ authClient, callbackURL, errorCallbackURL, onError, label, disabled, ...rest }: HgdcSignInButtonProps): ReactElement;
package/dist/react.js CHANGED
@@ -18,15 +18,23 @@ export async function startHgdcSignIn(authClient, { callbackURL = "/", errorCall
18
18
  return { ok: false, error };
19
19
  }
20
20
  }
21
- /** Monogramme HGDC, en `currentColor`. */
22
- export function HgdcMark(props) {
23
- return (_jsxs("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "currentColor", "aria-hidden": "true", ...props, children: [_jsx("rect", { x: "2.5", y: "8.5", width: "13", height: "7", rx: "2", transform: "rotate(45 9 12)" }), _jsx("rect", { x: "8.5", y: "8.5", width: "13", height: "7", rx: "2", transform: "rotate(45 15 12)", opacity: "0.6" })] }));
21
+ /**
22
+ * Le H tricolore de la famille, copie exacte de `@hgdc/ui/family/hfamily-icon.svg` (un test le
23
+ * vérifie) : `@hgdc/auth` ne dépend pas de `@hgdc/ui`.
24
+ */
25
+ export const HGDC_MARK_SVG = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><defs><linearGradient id="l" x1="0" y1="24" x2="0" y2="232" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#2c78fd"/><stop offset="1" stop-color="#7343fe"/></linearGradient><linearGradient id="r" x1="0" y1="24" x2="0" y2="232" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fe5292"/><stop offset="1" stop-color="#ff9a46"/></linearGradient><linearGradient id="b" x1="64" y1="0" x2="192" y2="0" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#8145ff"/><stop offset="1" stop-color="#fe5292"/></linearGradient></defs><rect x="43" y="24" width="57" height="208" rx="18" fill="url(#l)"/><rect x="156" y="24" width="57" height="208" rx="18" fill="url(#r)"/><rect x="67" y="107" width="122" height="43" rx="14" fill="url(#b)"/></svg>';
26
+ /**
27
+ * Le H tricolore de la famille, en image : ses dégradés gardent leurs identifiants pour eux, deux
28
+ * marques dans une page ne se marchent pas dessus. Couleurs pleines, jamais recolorées.
29
+ */
30
+ export function HgdcMark({ className }) {
31
+ return (_jsx("img", { src: `data:image/svg+xml,${encodeURIComponent(HGDC_MARK_SVG)}`, alt: "", "aria-hidden": "true", width: 16, height: 16, draggable: false, className: className }));
24
32
  }
25
33
  /**
26
- * Bouton « Se connecter avec HGDC ». Sans style propre : le produit le met en forme par
34
+ * Bouton « Se connecter avec H family ». Sans style propre : le produit le met en forme par
27
35
  * `className`, l'état d'attente est exposé par `aria-busy` et `data-pending`.
28
36
  */
29
- export function HgdcSignInButton({ authClient, callbackURL = "/", errorCallbackURL, onError, label = "Se connecter avec HGDC", disabled, ...rest }) {
37
+ export function HgdcSignInButton({ authClient, callbackURL = "/", errorCallbackURL, onError, label = "Se connecter avec H family", disabled, ...rest }) {
30
38
  const [pending, setPending] = useState(false);
31
39
  async function signIn() {
32
40
  setPending(true);
@@ -40,5 +48,5 @@ export function HgdcSignInButton({ authClient, callbackURL = "/", errorCallbackU
40
48
  onError?.(result.error);
41
49
  }
42
50
  }
43
- return (_jsxs("button", { ...rest, type: "button", disabled: disabled === true || pending, "aria-busy": pending, "data-pending": pending ? "" : undefined, onClick: () => void signIn(), children: [_jsx(HgdcMark, {}), _jsx("span", { children: pending ? "Redirection vers HGDC…" : label })] }));
51
+ return (_jsxs("button", { ...rest, type: "button", disabled: disabled === true || pending, "aria-busy": pending, "data-pending": pending ? "" : undefined, onClick: () => void signIn(), children: [_jsx(HgdcMark, {}), _jsx("span", { children: pending ? "Redirection vers Account…" : label })] }));
44
52
  }
package/dist/server.d.ts CHANGED
@@ -33,7 +33,7 @@ export type HgdcEntryOptions = {
33
33
  /**
34
34
  * Entrée commune `GET /auth/hgdc?next=<chemin>` (`HGDC_ENTRY_PATH`), à monter comme route
35
35
  * serveur du produit. Le menu « Produits » de `@hgdc/ui` y envoie : on entre dans le produit
36
- * sans passer par sa page d'accueil ni recliquer « Se connecter avec HGDC ».
36
+ * sans passer par sa page d'accueil ni recliquer « Se connecter avec H family ».
37
37
  *
38
38
  * - Session du produit ouverte : redirection vers `next`.
39
39
  * - Sinon : la connexion HGDC part aussitôt (même appel que `HgdcSignInButton`, fait par le
package/dist/server.js CHANGED
@@ -109,7 +109,7 @@ function authorizationUrl(body) {
109
109
  /**
110
110
  * Entrée commune `GET /auth/hgdc?next=<chemin>` (`HGDC_ENTRY_PATH`), à monter comme route
111
111
  * serveur du produit. Le menu « Produits » de `@hgdc/ui` y envoie : on entre dans le produit
112
- * sans passer par sa page d'accueil ni recliquer « Se connecter avec HGDC ».
112
+ * sans passer par sa page d'accueil ni recliquer « Se connecter avec H family ».
113
113
  *
114
114
  * - Session du produit ouverte : redirection vers `next`.
115
115
  * - Sinon : la connexion HGDC part aussitôt (même appel que `HgdcSignInButton`, fait par le
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hgdc/auth",
3
- "version": "0.5.0",
3
+ "version": "0.6.1",
4
4
  "description": "Connexion HGDC : bouton « Se connecter avec HGDC », config better-auth et gardes Convex.",
5
5
  "license": "UNLICENSED",
6
6
  "homepage": "https://github.com/hugogebel-boop/hgdc-kit/tree/main/packages/auth#readme",