@kourouma/express-authkit 0.0.0-stage → 0.1.0-rc.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.
Files changed (62) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/LICENSE +21 -0
  3. package/README.md +218 -2
  4. package/SECURITY.md +30 -0
  5. package/bin/express-authkit.js +30 -0
  6. package/package.json +93 -4
  7. package/src/adapters/express/bearer-token.js +35 -0
  8. package/src/adapters/express/http-errors.js +89 -0
  9. package/src/adapters/express/index.js +405 -0
  10. package/src/config/assertions.js +80 -0
  11. package/src/config/auth-kit-options.js +61 -0
  12. package/src/config/defaults.js +66 -0
  13. package/src/config/jwt-options.js +86 -0
  14. package/src/config/password-options.js +38 -0
  15. package/src/config/refresh-token-options.js +49 -0
  16. package/src/config/secret-strength.js +112 -0
  17. package/src/core/authentication-service.js +278 -0
  18. package/src/core/authorization.js +156 -0
  19. package/src/core/contracts/assert-contract.js +26 -0
  20. package/src/core/contracts/auth-principal.js +36 -0
  21. package/src/core/contracts/authentication-service.js +44 -0
  22. package/src/core/contracts/password-provider.js +27 -0
  23. package/src/core/contracts/refresh-token-store.js +80 -0
  24. package/src/core/contracts/token-provider.js +45 -0
  25. package/src/core/contracts/user-repository.js +157 -0
  26. package/src/core/errors.js +258 -0
  27. package/src/core/input-limits.js +26 -0
  28. package/src/core/messages.js +239 -0
  29. package/src/core/refresh-token-service.js +149 -0
  30. package/src/factory/create-auth-kit.js +90 -0
  31. package/src/index.js +61 -0
  32. package/src/providers/argon2-password-provider.js +68 -0
  33. package/src/providers/in-memory-refresh-token-store.js +51 -0
  34. package/src/providers/jwt-token-provider.js +112 -0
  35. package/types/adapters/express/bearer-token.d.ts +11 -0
  36. package/types/adapters/express/http-errors.d.ts +30 -0
  37. package/types/adapters/express/index.d.ts +57 -0
  38. package/types/config/assertions.d.ts +40 -0
  39. package/types/config/auth-kit-options.d.ts +41 -0
  40. package/types/config/defaults.d.ts +55 -0
  41. package/types/config/jwt-options.d.ts +42 -0
  42. package/types/config/password-options.d.ts +23 -0
  43. package/types/config/refresh-token-options.d.ts +21 -0
  44. package/types/config/secret-strength.d.ts +7 -0
  45. package/types/core/authentication-service.d.ts +37 -0
  46. package/types/core/authorization.d.ts +40 -0
  47. package/types/core/contracts/assert-contract.d.ts +13 -0
  48. package/types/core/contracts/auth-principal.d.ts +38 -0
  49. package/types/core/contracts/authentication-service.d.ts +102 -0
  50. package/types/core/contracts/password-provider.d.ts +32 -0
  51. package/types/core/contracts/refresh-token-store.d.ts +105 -0
  52. package/types/core/contracts/token-provider.d.ts +79 -0
  53. package/types/core/contracts/user-repository.d.ts +112 -0
  54. package/types/core/errors.d.ts +213 -0
  55. package/types/core/input-limits.d.ts +20 -0
  56. package/types/core/messages.d.ts +141 -0
  57. package/types/core/refresh-token-service.d.ts +31 -0
  58. package/types/factory/create-auth-kit.d.ts +52 -0
  59. package/types/index.d.ts +60 -0
  60. package/types/providers/argon2-password-provider.d.ts +13 -0
  61. package/types/providers/in-memory-refresh-token-store.d.ts +11 -0
  62. package/types/providers/jwt-token-provider.d.ts +13 -0
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Identifiants transmis par un client.
3
+ *
4
+ * @typedef {object} LoginCredentials
5
+ * @property {string} identifier Identifiant de connexion (e-mail, nom d’utilisateur…).
6
+ * @property {string} password Mot de passe en clair. Il n’est ni journalisé ni stocké.
7
+ */
8
+ export type LoginCredentials = {
9
+ /**
10
+ * Identifiant de connexion (e-mail, nom d’utilisateur…).
11
+ */
12
+ identifier: string;
13
+ /**
14
+ * Mot de passe en clair. Il n’est ni journalisé ni stocké.
15
+ */
16
+ password: string;
17
+ };
18
+ export type LoginResult = {
19
+ /**
20
+ * Jeton d’accès JWT signé.
21
+ */
22
+ accessToken: string;
23
+ /**
24
+ * Toujours `"Bearer"`.
25
+ */
26
+ tokenType: "Bearer";
27
+ /**
28
+ * Durée de vie du jeton, en secondes.
29
+ */
30
+ expiresIn: number;
31
+ /**
32
+ * Identité authentifiée.
33
+ */
34
+ principal: import("./auth-principal.js").AuthPrincipal;
35
+ /**
36
+ * Jeton de rafraîchissement (présent si `refreshTokens` est activé).
37
+ */
38
+ refreshToken?: string;
39
+ /**
40
+ * Durée de vie du jeton de rafraîchissement, en secondes.
41
+ */
42
+ refreshExpiresIn?: number;
43
+ };
44
+ export type UserIdInput = string | number | bigint | {
45
+ toHexString(): string;
46
+ };
47
+ export type AuthenticationService = {
48
+ /**
49
+ * Authentifie un utilisateur. Renvoie `InvalidCredentialsError` pour un
50
+ * utilisateur inconnu, un mauvais mot de passe ou un compte désactivé.
51
+ */
52
+ login: (credentials: LoginCredentials) => Promise<LoginResult>;
53
+ /**
54
+ * Échange un jeton de rafraîchissement contre une nouvelle paire de jetons (rotation).
55
+ */
56
+ refresh: (refreshToken: string) => Promise<LoginResult>;
57
+ /**
58
+ * Révoque la session liée au jeton de rafraîchissement.
59
+ */
60
+ logout: (refreshToken: string) => Promise<void>;
61
+ /**
62
+ * Révoque toutes les sessions d’un utilisateur.
63
+ */
64
+ revokeAllSessions: (userId: UserIdInput) => Promise<void>;
65
+ /**
66
+ * Vérifie un jeton et contrôle que son utilisateur existe et est toujours actif.
67
+ */
68
+ verifyAccessToken: (token: string) => Promise<import("./auth-principal.js").AuthPrincipal>;
69
+ };
70
+ /**
71
+ * Résultat d’une connexion réussie, envoyable tel quel dans une réponse HTTP.
72
+ *
73
+ * @typedef {object} LoginResult
74
+ * @property {string} accessToken Jeton d’accès JWT signé.
75
+ * @property {"Bearer"} tokenType Toujours `"Bearer"`.
76
+ * @property {number} expiresIn Durée de vie du jeton, en secondes.
77
+ * @property {import("./auth-principal.js").AuthPrincipal} principal Identité authentifiée.
78
+ * @property {string} [refreshToken] Jeton de rafraîchissement (présent si `refreshTokens` est activé).
79
+ * @property {number} [refreshExpiresIn] Durée de vie du jeton de rafraîchissement, en secondes.
80
+ */
81
+ /**
82
+ * Forme acceptée pour un identifiant d’utilisateur : texte, entier, BigInt ou ObjectId MongoDB.
83
+ *
84
+ * @typedef {string | number | bigint | { toHexString(): string }} UserIdInput
85
+ */
86
+ /**
87
+ * Cas d’usage d’authentification indépendants du framework.
88
+ *
89
+ * @typedef {object} AuthenticationService
90
+ * @property {(credentials: LoginCredentials) => Promise<LoginResult>} login
91
+ * Authentifie un utilisateur. Renvoie `InvalidCredentialsError` pour un
92
+ * utilisateur inconnu, un mauvais mot de passe ou un compte désactivé.
93
+ * @property {(refreshToken: string) => Promise<LoginResult>} refresh
94
+ * Échange un jeton de rafraîchissement contre une nouvelle paire de jetons (rotation).
95
+ * @property {(refreshToken: string) => Promise<void>} logout
96
+ * Révoque la session liée au jeton de rafraîchissement.
97
+ * @property {(userId: UserIdInput) => Promise<void>} revokeAllSessions
98
+ * Révoque toutes les sessions d’un utilisateur.
99
+ * @property {(token: string) => Promise<import("./auth-principal.js").AuthPrincipal>} verifyAccessToken
100
+ * Vérifie un jeton et contrôle que son utilisateur existe et est toujours actif.
101
+ */
102
+ export {};
@@ -0,0 +1,32 @@
1
+ export type PasswordProvider = {
2
+ /**
3
+ * Renvoie un hash autonome (algorithme, paramètres et sel encodés dans la chaîne).
4
+ */
5
+ hash: (password: string) => Promise<string>;
6
+ /**
7
+ * Renvoie `true` si le mot de passe correspond. La comparaison doit être en
8
+ * temps constant et lever `InvalidPasswordHashError` si `hash` est illisible.
9
+ */
10
+ verify: (password: string, hash: string) => Promise<boolean>;
11
+ };
12
+ /**
13
+ * Contrat de hachage des mots de passe.
14
+ *
15
+ * Les implémentations doivent employer un algorithme éprouvé (le fournisseur
16
+ * par défaut utilise Argon2id) et ne jamais programmer la cryptographie elles-mêmes.
17
+ *
18
+ * @typedef {object} PasswordProvider
19
+ * @property {(password: string) => Promise<string>} hash
20
+ * Renvoie un hash autonome (algorithme, paramètres et sel encodés dans la chaîne).
21
+ * @property {(password: string, hash: string) => Promise<boolean>} verify
22
+ * Renvoie `true` si le mot de passe correspond. La comparaison doit être en
23
+ * temps constant et lever `InvalidPasswordHashError` si `hash` est illisible.
24
+ */
25
+ /** @type {readonly string[]} */
26
+ export declare const PASSWORD_PROVIDER_METHODS: readonly string[];
27
+ /**
28
+ * @param {unknown} provider
29
+ * @returns {asserts provider is PasswordProvider}
30
+ * @throws {import("../errors.js").ContractViolationError}
31
+ */
32
+ export declare function assertPasswordProvider(provider: unknown): asserts provider is PasswordProvider;
@@ -0,0 +1,105 @@
1
+ export type RefreshTokenRecord = {
2
+ /**
3
+ * Empreinte SHA-256 du jeton (64 caractères hexadécimaux). Clé unique.
4
+ */
5
+ tokenHash: string;
6
+ /**
7
+ * Identifiant de l’utilisateur.
8
+ */
9
+ userId: string;
10
+ /**
11
+ * Identifiant de la « famille » : tous les jetons issus d’une même connexion.
12
+ */
13
+ familyId: string;
14
+ /**
15
+ * Date d’expiration, en secondes depuis l’époque Unix.
16
+ */
17
+ expiresAt: number;
18
+ };
19
+ export type ConsumedRefreshToken = {
20
+ userId: string;
21
+ familyId: string;
22
+ /**
23
+ * Secondes depuis l’époque Unix.
24
+ */
25
+ expiresAt: number;
26
+ /**
27
+ * `true` si le jeton avait déjà été consommé avant cet appel.
28
+ */
29
+ alreadyUsed: boolean;
30
+ };
31
+ export type RefreshTokenStore = {
32
+ /**
33
+ * Enregistre un nouveau jeton.
34
+ */
35
+ save: (record: RefreshTokenRecord) => Promise<void>;
36
+ /**
37
+ * Marque le jeton comme utilisé et renvoie son état précédent, ou `null` s’il
38
+ * est inconnu. Doit être **atomique** : si deux requêtes consomment le même
39
+ * jeton en même temps, une seule doit obtenir `alreadyUsed: false`.
40
+ * Les jetons utilisés doivent être conservés jusqu’à leur expiration, pour
41
+ * détecter une réutilisation.
42
+ */
43
+ consume: (tokenHash: string) => Promise<ConsumedRefreshToken | null | undefined>;
44
+ /**
45
+ * Supprime (ou invalide) tous les jetons d’une famille.
46
+ */
47
+ revokeFamily: (familyId: string) => Promise<void>;
48
+ /**
49
+ * Supprime (ou invalide) tous les jetons d’un utilisateur.
50
+ */
51
+ revokeUser: (userId: string) => Promise<void>;
52
+ };
53
+ /**
54
+ * Jeton de rafraîchissement tel qu’il est enregistré. Le jeton lui-même n’est
55
+ * jamais stocké : seule son empreinte SHA-256 l’est. Une fuite de la base ne
56
+ * donne donc aucun jeton utilisable.
57
+ *
58
+ * @typedef {object} RefreshTokenRecord
59
+ * @property {string} tokenHash Empreinte SHA-256 du jeton (64 caractères hexadécimaux). Clé unique.
60
+ * @property {string} userId Identifiant de l’utilisateur.
61
+ * @property {string} familyId Identifiant de la « famille » : tous les jetons issus d’une même connexion.
62
+ * @property {number} expiresAt Date d’expiration, en secondes depuis l’époque Unix.
63
+ */
64
+ /**
65
+ * Résultat de {@link RefreshTokenStore.consume}.
66
+ *
67
+ * @typedef {object} ConsumedRefreshToken
68
+ * @property {string} userId
69
+ * @property {string} familyId
70
+ * @property {number} expiresAt Secondes depuis l’époque Unix.
71
+ * @property {boolean} alreadyUsed `true` si le jeton avait déjà été consommé avant cet appel.
72
+ */
73
+ /**
74
+ * Stockage des jetons de rafraîchissement, implémenté par l’application.
75
+ *
76
+ * @typedef {object} RefreshTokenStore
77
+ * @property {(record: RefreshTokenRecord) => Promise<void>} save
78
+ * Enregistre un nouveau jeton.
79
+ * @property {(tokenHash: string) => Promise<ConsumedRefreshToken | null | undefined>} consume
80
+ * Marque le jeton comme utilisé et renvoie son état précédent, ou `null` s’il
81
+ * est inconnu. Doit être **atomique** : si deux requêtes consomment le même
82
+ * jeton en même temps, une seule doit obtenir `alreadyUsed: false`.
83
+ * Les jetons utilisés doivent être conservés jusqu’à leur expiration, pour
84
+ * détecter une réutilisation.
85
+ * @property {(familyId: string) => Promise<void>} revokeFamily
86
+ * Supprime (ou invalide) tous les jetons d’une famille.
87
+ * @property {(userId: string) => Promise<void>} revokeUser
88
+ * Supprime (ou invalide) tous les jetons d’un utilisateur.
89
+ */
90
+ /** @type {readonly string[]} */
91
+ export declare const REFRESH_TOKEN_STORE_METHODS: readonly string[];
92
+ /**
93
+ * @param {unknown} store
94
+ * @returns {asserts store is RefreshTokenStore}
95
+ * @throws {ContractViolationError}
96
+ */
97
+ export declare function assertRefreshTokenStore(store: unknown): asserts store is RefreshTokenStore;
98
+ /**
99
+ * Valide à l’exécution la valeur renvoyée par `consume()`.
100
+ *
101
+ * @param {unknown} result
102
+ * @returns {ConsumedRefreshToken | null}
103
+ * @throws {ContractViolationError}
104
+ */
105
+ export declare function normalizeConsumedRefreshToken(result: unknown): ConsumedRefreshToken | null;
@@ -0,0 +1,79 @@
1
+ export type IssuedToken = {
2
+ /**
3
+ * Jeton sérialisé.
4
+ */
5
+ token: string;
6
+ /**
7
+ * Identifiant unique du jeton (`jti`).
8
+ */
9
+ tokenId: string;
10
+ /**
11
+ * Date d’émission, en secondes depuis l’époque Unix.
12
+ */
13
+ issuedAt: number;
14
+ /**
15
+ * Date d’expiration, en secondes depuis l’époque Unix.
16
+ */
17
+ expiresAt: number;
18
+ };
19
+ export type VerifiedTokenClaims = {
20
+ /**
21
+ * Identifiant utilisateur (`sub`).
22
+ */
23
+ subject: string;
24
+ /**
25
+ * Identifiant du jeton (`jti`).
26
+ */
27
+ tokenId: string;
28
+ /**
29
+ * `iat`, en secondes depuis l’époque Unix.
30
+ */
31
+ issuedAt: number;
32
+ /**
33
+ * `exp`, en secondes depuis l’époque Unix.
34
+ */
35
+ expiresAt: number;
36
+ };
37
+ export type TokenProvider = {
38
+ issue: (input: {
39
+ subject: string;
40
+ }) => Promise<IssuedToken>;
41
+ verify: (token: string) => Promise<VerifiedTokenClaims>;
42
+ };
43
+ /**
44
+ * Résultat de l’émission d’un jeton d’accès.
45
+ *
46
+ * @typedef {object} IssuedToken
47
+ * @property {string} token Jeton sérialisé.
48
+ * @property {string} tokenId Identifiant unique du jeton (`jti`).
49
+ * @property {number} issuedAt Date d’émission, en secondes depuis l’époque Unix.
50
+ * @property {number} expiresAt Date d’expiration, en secondes depuis l’époque Unix.
51
+ */
52
+ /**
53
+ * Revendications extraites d’un jeton d’accès vérifié.
54
+ *
55
+ * @typedef {object} VerifiedTokenClaims
56
+ * @property {string} subject Identifiant utilisateur (`sub`).
57
+ * @property {string} tokenId Identifiant du jeton (`jti`).
58
+ * @property {number} issuedAt `iat`, en secondes depuis l’époque Unix.
59
+ * @property {number} expiresAt `exp`, en secondes depuis l’époque Unix.
60
+ */
61
+ /**
62
+ * Contrat de gestion des jetons d’accès.
63
+ *
64
+ * `verify()` doit contrôler la signature, les algorithmes autorisés, l’expiration,
65
+ * l’émetteur, l’audience et le sujet. Elle lève `TokenExpiredError` pour un jeton
66
+ * expiré et `InvalidTokenError` pour tout autre rejet.
67
+ *
68
+ * @typedef {object} TokenProvider
69
+ * @property {(input: { subject: string }) => Promise<IssuedToken>} issue
70
+ * @property {(token: string) => Promise<VerifiedTokenClaims>} verify
71
+ */
72
+ /** @type {readonly string[]} */
73
+ export declare const TOKEN_PROVIDER_METHODS: readonly string[];
74
+ /**
75
+ * @param {unknown} provider
76
+ * @returns {asserts provider is TokenProvider}
77
+ * @throws {import("../errors.js").ContractViolationError}
78
+ */
79
+ export declare function assertTokenProvider(provider: unknown): asserts provider is TokenProvider;
@@ -0,0 +1,112 @@
1
+ export type AuthUserRecord = {
2
+ /**
3
+ * Identifiant stable, unique et non secret (chaîne, entier ou ObjectId MongoDB) ; converti en chaîne, il devient la revendication JWT `sub`.
4
+ */
5
+ id: string | number | bigint | {
6
+ toHexString(): string;
7
+ };
8
+ /**
9
+ * Hash Argon2id produit par `auth.password.hash()`.
10
+ */
11
+ passwordHash: string;
12
+ /**
13
+ * Doit valoir exactement `true` pour autoriser la connexion.
14
+ */
15
+ isActive: boolean;
16
+ /**
17
+ * Rôles de l’utilisateur (par exemple `["admin"]`). Facultatif.
18
+ */
19
+ roles?: string[];
20
+ /**
21
+ * Permissions de l’utilisateur (par exemple `["orders:write"]`). Facultatif.
22
+ */
23
+ permissions?: string[];
24
+ };
25
+ export type NormalizedUserRecord = {
26
+ id: string;
27
+ passwordHash: string;
28
+ isActive: boolean;
29
+ roles: readonly string[];
30
+ permissions: readonly string[];
31
+ };
32
+ export type UserRepository = {
33
+ /**
34
+ * Cherche un utilisateur par identifiant de connexion (e-mail, nom…). La
35
+ * normalisation (minuscules, espaces) relève de la responsabilité du dépôt.
36
+ */
37
+ findByIdentifier: (identifier: string) => Promise<AuthUserRecord | null | undefined>;
38
+ /**
39
+ * Cherche un utilisateur par l’identifiant contenu dans la revendication `sub`.
40
+ */
41
+ findById: (id: string) => Promise<AuthUserRecord | null | undefined>;
42
+ };
43
+ /**
44
+ * Données utilisateur minimales attendues par le moteur. Le dépôt transforme
45
+ * son modèle (ligne SQL, document Mongo, réponse d’API…) dans ce format.
46
+ *
47
+ * Les propriétés supplémentaires sont autorisées et ignorées. Elles ne sont
48
+ * jamais copiées dans les jetons ni dans le principal authentifié.
49
+ *
50
+ * @typedef {object} AuthUserRecord
51
+ * @property {string | number | bigint | { toHexString(): string }} id Identifiant stable, unique et non secret (chaîne, entier ou ObjectId MongoDB) ; converti en chaîne, il devient la revendication JWT `sub`.
52
+ * @property {string} passwordHash Hash Argon2id produit par `auth.password.hash()`.
53
+ * @property {boolean} isActive Doit valoir exactement `true` pour autoriser la connexion.
54
+ * @property {string[]} [roles] Rôles de l’utilisateur (par exemple `["admin"]`). Facultatif.
55
+ * @property {string[]} [permissions] Permissions de l’utilisateur (par exemple `["orders:write"]`). Facultatif.
56
+ */
57
+ /**
58
+ * Enregistrement validé et normalisé, utilisé par le moteur.
59
+ *
60
+ * @typedef {{
61
+ * id: string,
62
+ * passwordHash: string,
63
+ * isActive: boolean,
64
+ * roles: readonly string[],
65
+ * permissions: readonly string[]
66
+ * }} NormalizedUserRecord
67
+ */
68
+ /**
69
+ * Contrat de persistance implémenté par l’application.
70
+ *
71
+ * Les deux méthodes doivent renvoyer `null` (ou `undefined`) lorsqu’aucun
72
+ * utilisateur ne correspond. Elles ne doivent pas lever d’erreur dans ce cas ;
73
+ * les erreurs sont réservées aux problèmes d’infrastructure.
74
+ *
75
+ * @typedef {object} UserRepository
76
+ * @property {(identifier: string) => Promise<AuthUserRecord | null | undefined>} findByIdentifier
77
+ * Cherche un utilisateur par identifiant de connexion (e-mail, nom…). La
78
+ * normalisation (minuscules, espaces) relève de la responsabilité du dépôt.
79
+ * @property {(id: string) => Promise<AuthUserRecord | null | undefined>} findById
80
+ * Cherche un utilisateur par l’identifiant contenu dans la revendication `sub`.
81
+ */
82
+ /** @type {readonly string[]} */
83
+ export declare const USER_REPOSITORY_METHODS: readonly string[];
84
+ /**
85
+ * Vérifie qu’un dépôt injecté respecte le contrat {@link UserRepository}.
86
+ *
87
+ * @param {unknown} repository
88
+ * @returns {asserts repository is UserRepository}
89
+ * @throws {ContractViolationError}
90
+ */
91
+ export declare function assertUserRepository(repository: unknown): asserts repository is UserRepository;
92
+ /**
93
+ * Valide à l’exécution une donnée renvoyée par le dépôt.
94
+ *
95
+ * Une donnée mal formée est une erreur de programmation. Elle lève donc
96
+ * {@link ContractViolationError} au lieu d’être traitée comme un échec de
97
+ * connexion, ce qui masquerait le problème.
98
+ *
99
+ * @param {unknown} record
100
+ * @returns {NormalizedUserRecord | null} Enregistrement avec un `id` toujours en texte.
101
+ * @throws {ContractViolationError}
102
+ */
103
+ export declare function normalizeUserRecord(record: unknown): NormalizedUserRecord | null;
104
+ /**
105
+ * Accepte les formes d’identifiant les plus courantes et les convertit en
106
+ * chaîne : texte, entier auto-incrémenté (SQL), BigInt et ObjectId MongoDB.
107
+ * La conversion est sans perte, ce qui évite aux applications de l’écrire.
108
+ *
109
+ * @param {unknown} id
110
+ * @returns {string | null} L’identifiant en texte, ou `null` si sa forme n’est pas prise en charge.
111
+ */
112
+ export declare function toUserIdString(id: unknown): string | null;
@@ -0,0 +1,213 @@
1
+ /**
2
+ * Types d’erreurs structurées pour Express AuthKit.
3
+ *
4
+ * Chaque erreur expose un `code` stable, utilisable par les applications.
5
+ * Ces codes font partie de l’API publique. Le cœur n’associe jamais les
6
+ * erreurs à des statuts HTTP : c’est le rôle des adaptateurs.
7
+ *
8
+ * @module core/errors
9
+ */
10
+ /**
11
+ * Codes d’erreur stables exposés par la bibliothèque.
12
+ *
13
+ * @readonly
14
+ * @enum {string}
15
+ */
16
+ export declare const AUTH_ERROR_CODES: Readonly<{
17
+ /** Échec de connexion, volontairement générique pour éviter l’énumération des comptes. */
18
+ INVALID_CREDENTIALS: "INVALID_CREDENTIALS";
19
+ /** Donnée invalide (mauvais type, vide ou trop longue). */
20
+ INVALID_INPUT: "INVALID_INPUT";
21
+ /** Aucun jeton d’accès n’a été fourni. */
22
+ TOKEN_MISSING: "TOKEN_MISSING";
23
+ /** Le jeton est mal formé, altéré, signé avec une autre clé ou contient des revendications invalides. */
24
+ TOKEN_INVALID: "TOKEN_INVALID";
25
+ /** La signature du jeton est valide, mais le jeton a expiré. */
26
+ TOKEN_EXPIRED: "TOKEN_EXPIRED";
27
+ /** Le moteur est configuré avec des options manquantes ou non sûres. */
28
+ INVALID_CONFIGURATION: "INVALID_CONFIGURATION";
29
+ /** Une dépendance injectée ne respecte pas son contrat. */
30
+ CONTRACT_VIOLATION: "CONTRACT_VIOLATION";
31
+ /** Le fournisseur de mots de passe ne peut pas lire un hash stocké. */
32
+ INVALID_PASSWORD_HASH: "INVALID_PASSWORD_HASH";
33
+ /** L’utilisateur est authentifié mais n’a pas les rôles ou permissions requis. */
34
+ ACCESS_DENIED: "ACCESS_DENIED";
35
+ /** Le jeton de rafraîchissement est inconnu, expiré, déjà utilisé ou révoqué. */
36
+ REFRESH_TOKEN_INVALID: "REFRESH_TOKEN_INVALID";
37
+ /** Une dépendance injectée (repository, provider) a échoué de façon inattendue. */
38
+ DEPENDENCY_FAILURE: "DEPENDENCY_FAILURE";
39
+ }>;
40
+ /**
41
+ * Raisons internes associées aux échecs d’authentification.
42
+ *
43
+ * Elles servent uniquement à l’audit côté serveur et ne doivent jamais être
44
+ * envoyées au client, car elles révéleraient l’existence d’un compte.
45
+ *
46
+ * @readonly
47
+ * @enum {string}
48
+ */
49
+ export declare const AUTH_FAILURE_REASONS: Readonly<{
50
+ USER_NOT_FOUND: "USER_NOT_FOUND";
51
+ INVALID_PASSWORD: "INVALID_PASSWORD";
52
+ ACCOUNT_DISABLED: "ACCOUNT_DISABLED";
53
+ /** Jeton de rafraîchissement absent du stockage (jamais émis, ou révoqué). */
54
+ REFRESH_TOKEN_UNKNOWN: "REFRESH_TOKEN_UNKNOWN";
55
+ /** Jeton de rafraîchissement expiré. */
56
+ REFRESH_TOKEN_EXPIRED: "REFRESH_TOKEN_EXPIRED";
57
+ /** Jeton de rafraîchissement déjà utilisé : vol probable, toute la famille est révoquée. */
58
+ REFRESH_TOKEN_REUSED: "REFRESH_TOKEN_REUSED";
59
+ }>;
60
+ /**
61
+ * Classe de base de toutes les erreurs levées par Express AuthKit.
62
+ */
63
+ export declare class AuthKitError extends Error {
64
+ /** @type {string} */
65
+ code: string;
66
+ /**
67
+ * @param {string} code Code d’erreur stable (voir {@link AUTH_ERROR_CODES}).
68
+ * @param {string} message Message pouvant être exposé aux clients de l’API.
69
+ * @param {{ cause?: unknown }} [options]
70
+ */
71
+ constructor(code: string, message: string, options?: {
72
+ cause?: unknown;
73
+ });
74
+ /**
75
+ * Représentation sûre pour les journaux et `JSON.stringify()` : ni pile
76
+ * d’appels, ni cause, ni raison interne.
77
+ *
78
+ * @returns {{ name: string, code: string, message: string }}
79
+ */
80
+ toJSON(): {
81
+ name: string;
82
+ code: string;
83
+ message: string;
84
+ };
85
+ }
86
+ /**
87
+ * Échec de connexion. Le message public ne précise jamais la cause.
88
+ */
89
+ export declare class InvalidCredentialsError extends AuthKitError {
90
+ /**
91
+ * @param {string} [reason] Raison d’audit interne (voir {@link AUTH_FAILURE_REASONS}).
92
+ */
93
+ constructor(reason?: string);
94
+ }
95
+ /**
96
+ * Donnée structurellement invalide reçue à une frontière de confiance.
97
+ */
98
+ export declare class InvalidInputError extends AuthKitError {
99
+ /**
100
+ * @param {string} message
101
+ */
102
+ constructor(message: string);
103
+ }
104
+ /**
105
+ * Jeton d’accès absent de la requête.
106
+ */
107
+ export declare class TokenMissingError extends AuthKitError {
108
+ constructor();
109
+ }
110
+ /**
111
+ * Jeton d’accès rejeté (mal formé, altéré, mauvais émetteur ou audience, utilisateur inconnu ou désactivé…).
112
+ */
113
+ export declare class InvalidTokenError extends AuthKitError {
114
+ /**
115
+ * @param {{ cause?: unknown, reason?: string }} [options]
116
+ */
117
+ constructor(options?: {
118
+ cause?: unknown;
119
+ reason?: string;
120
+ });
121
+ }
122
+ /**
123
+ * Jeton d’accès dont la signature est valide, mais qui a expiré.
124
+ */
125
+ export declare class TokenExpiredError extends AuthKitError {
126
+ /**
127
+ * @param {{ cause?: unknown }} [options]
128
+ */
129
+ constructor(options?: {
130
+ cause?: unknown;
131
+ });
132
+ }
133
+ /**
134
+ * Utilisateur authentifié, mais sans les droits demandés (rôle, permission ou
135
+ * règle personnalisée). Le message ne dit pas quel droit manque.
136
+ */
137
+ export declare class AccessDeniedError extends AuthKitError {
138
+ constructor();
139
+ }
140
+ /**
141
+ * Jeton de rafraîchissement refusé. Le message public est toujours le même ;
142
+ * la cause précise est dans `reason` (non énumérable), pour les journaux.
143
+ */
144
+ export declare class InvalidRefreshTokenError extends AuthKitError {
145
+ /**
146
+ * @param {string} [reason] Raison d’audit interne (voir {@link AUTH_FAILURE_REASONS}).
147
+ */
148
+ constructor(reason?: string);
149
+ }
150
+ /**
151
+ * Configuration manquante, mal formée ou non sûre, levée à l’initialisation.
152
+ */
153
+ export declare class ConfigurationError extends AuthKitError {
154
+ /**
155
+ * @param {string} message
156
+ */
157
+ constructor(message: string);
158
+ }
159
+ /**
160
+ * Dépendance injectée qui n’implémente pas son contrat.
161
+ */
162
+ export declare class ContractViolationError extends AuthKitError {
163
+ /**
164
+ * @param {string} message
165
+ */
166
+ constructor(message: string);
167
+ }
168
+ /**
169
+ * Hash de mot de passe stocké que le fournisseur ne peut pas lire. Cela vient
170
+ * généralement d’une migration de données (par exemple bcrypt avec Argon2).
171
+ */
172
+ export declare class InvalidPasswordHashError extends AuthKitError {
173
+ /**
174
+ * @param {{ cause?: unknown }} [options]
175
+ */
176
+ constructor(options?: {
177
+ cause?: unknown;
178
+ });
179
+ }
180
+ /**
181
+ * Échec inattendu d’une dépendance injectée : base de données indisponible,
182
+ * service distant en panne, bug dans un provider personnalisé…
183
+ *
184
+ * L’erreur d’origine est conservée dans `cause` pour le diagnostic. Elle n’est
185
+ * jamais exposée aux clients HTTP par l’adaptateur Express.
186
+ */
187
+ export declare class DependencyFailureError extends AuthKitError {
188
+ /** @type {string} */
189
+ dependency: string;
190
+ /**
191
+ * @param {string} dependency Nom de l’appel qui a échoué, par exemple « UserRepository.findById ».
192
+ * @param {unknown} cause Erreur d’origine.
193
+ */
194
+ constructor(dependency: string, cause: unknown);
195
+ }
196
+ /**
197
+ * Exécute l’appel à une dépendance injectée. Les erreurs de la bibliothèque
198
+ * (jeton expiré, hash illisible…) sont transmises telles quelles ; toute autre
199
+ * erreur est enveloppée dans une {@link DependencyFailureError}.
200
+ *
201
+ * @template T
202
+ * @param {string} dependency
203
+ * @param {() => Promise<T> | T} call
204
+ * @returns {Promise<T>}
205
+ */
206
+ export declare function callDependency<T>(dependency: string, call: () => Promise<T> | T): Promise<T>;
207
+ /**
208
+ * Garde de type pour les erreurs levées par Express AuthKit.
209
+ *
210
+ * @param {unknown} error
211
+ * @returns {error is AuthKitError}
212
+ */
213
+ export declare function isAuthKitError(error: unknown): error is AuthKitError;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Limites appliquées aux données non fiables avant tout traitement coûteux.
3
+ *
4
+ * Elles évitent l’épuisement des ressources par des valeurs trop longues tout
5
+ * en restant largement au-dessus des besoins légitimes.
6
+ *
7
+ * @module core/input-limits
8
+ */
9
+ /** Longueur maximale d’un e-mail selon la RFC 5321, suffisante aussi pour un nom d’utilisateur. */
10
+ export declare const MAX_IDENTIFIER_LENGTH = 320;
11
+ /** Suffisante pour les phrases de passe, tout en limitant le coût du hachage. */
12
+ export declare const MAX_PASSWORD_LENGTH = 1024;
13
+ /** Les jetons d’accès produits par cette bibliothèque font quelques centaines de caractères. */
14
+ export declare const MAX_TOKEN_LENGTH = 8192;
15
+ /** Les jetons de rafraîchissement émis font 43 caractères ; la marge couvre d’autres formats. */
16
+ export declare const MAX_REFRESH_TOKEN_LENGTH = 512;
17
+ /** Nombre maximal de rôles (ou de permissions) par utilisateur : borne le coût des vérifications. */
18
+ export declare const MAX_AUTHORITIES = 256;
19
+ /** Longueur maximale d’un nom de rôle ou de permission (par exemple « orders:write »). */
20
+ export declare const MAX_AUTHORITY_LENGTH = 128;