@fluixi/oauth2 1.0.0-alpha.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 (116) hide show
  1. package/LICENSE +21 -0
  2. package/dist/api-guard.cjs +185 -0
  3. package/dist/api-guard.d.ts +94 -0
  4. package/dist/api-guard.d.ts.map +1 -0
  5. package/dist/api-guard.js +127 -0
  6. package/dist/api-guard.mjs +141 -0
  7. package/dist/browser-FDUOEUM2.mjs +3544 -0
  8. package/dist/browser-ONMHX3Z3.mjs +3545 -0
  9. package/dist/browser.cjs +735 -0
  10. package/dist/browser.d.ts +3 -0
  11. package/dist/browser.d.ts.map +1 -0
  12. package/dist/browser.js +448 -0
  13. package/dist/browser.mjs +704 -0
  14. package/dist/callback.cjs +125 -0
  15. package/dist/callback.d.ts +113 -0
  16. package/dist/callback.d.ts.map +1 -0
  17. package/dist/callback.js +183 -0
  18. package/dist/callback.mjs +106 -0
  19. package/dist/chunk-25WE6UWI.mjs +10 -0
  20. package/dist/chunk-4NSOGPLM.mjs +15 -0
  21. package/dist/chunk-7P6ASYW6.mjs +9 -0
  22. package/dist/chunk-OGSFNTKA.mjs +13 -0
  23. package/dist/client-auth.cjs +115 -0
  24. package/dist/client-auth.d.ts +43 -0
  25. package/dist/client-auth.d.ts.map +1 -0
  26. package/dist/client-auth.js +112 -0
  27. package/dist/client-auth.mjs +84 -0
  28. package/dist/discovery.cjs +86 -0
  29. package/dist/discovery.d.ts +15 -0
  30. package/dist/discovery.d.ts.map +1 -0
  31. package/dist/discovery.js +51 -0
  32. package/dist/discovery.mjs +63 -0
  33. package/dist/dpop-LVPWWADA.mjs +80 -0
  34. package/dist/dpop-NS7NKOWM.mjs +79 -0
  35. package/dist/dpop-store.cjs +152 -0
  36. package/dist/dpop-store.d.ts +37 -0
  37. package/dist/dpop-store.d.ts.map +1 -0
  38. package/dist/dpop-store.js +119 -0
  39. package/dist/dpop-store.mjs +121 -0
  40. package/dist/dpop.cjs +117 -0
  41. package/dist/dpop.d.ts +72 -0
  42. package/dist/dpop.d.ts.map +1 -0
  43. package/dist/dpop.js +114 -0
  44. package/dist/dpop.mjs +86 -0
  45. package/dist/env-config.cjs +366 -0
  46. package/dist/env-config.d.ts +103 -0
  47. package/dist/env-config.d.ts.map +1 -0
  48. package/dist/env-config.js +184 -0
  49. package/dist/env-config.mjs +343 -0
  50. package/dist/env-credentials.cjs +82 -0
  51. package/dist/env-credentials.d.ts +68 -0
  52. package/dist/env-credentials.d.ts.map +1 -0
  53. package/dist/env-credentials.js +76 -0
  54. package/dist/env-credentials.mjs +51 -0
  55. package/dist/index.cjs +940 -0
  56. package/dist/index.d.ts +104 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +101 -0
  59. package/dist/index.mjs +909 -0
  60. package/dist/pkce.cjs +87 -0
  61. package/dist/pkce.d.ts +58 -0
  62. package/dist/pkce.d.ts.map +1 -0
  63. package/dist/pkce.js +112 -0
  64. package/dist/pkce.mjs +66 -0
  65. package/dist/presets.cjs +240 -0
  66. package/dist/presets.d.ts +140 -0
  67. package/dist/presets.d.ts.map +1 -0
  68. package/dist/presets.js +182 -0
  69. package/dist/presets.mjs +217 -0
  70. package/dist/return-to.cjs +46 -0
  71. package/dist/return-to.d.ts +49 -0
  72. package/dist/return-to.d.ts.map +1 -0
  73. package/dist/return-to.js +71 -0
  74. package/dist/return-to.mjs +25 -0
  75. package/dist/roles.cjs +56 -0
  76. package/dist/roles.d.ts +35 -0
  77. package/dist/roles.d.ts.map +1 -0
  78. package/dist/roles.js +37 -0
  79. package/dist/roles.mjs +35 -0
  80. package/dist/server-client.cjs +134 -0
  81. package/dist/server-client.d.ts +12 -0
  82. package/dist/server-client.d.ts.map +1 -0
  83. package/dist/server-client.js +107 -0
  84. package/dist/server-client.mjs +111 -0
  85. package/dist/server.cjs +470 -0
  86. package/dist/server.d.ts +89 -0
  87. package/dist/server.d.ts.map +1 -0
  88. package/dist/server.js +360 -0
  89. package/dist/server.mjs +441 -0
  90. package/dist/service-client.cjs +244 -0
  91. package/dist/service-client.d.ts +89 -0
  92. package/dist/service-client.d.ts.map +1 -0
  93. package/dist/service-client.js +112 -0
  94. package/dist/service-client.mjs +213 -0
  95. package/dist/service.cjs +903 -0
  96. package/dist/service.d.ts +96 -0
  97. package/dist/service.d.ts.map +1 -0
  98. package/dist/service.js +129 -0
  99. package/dist/service.mjs +874 -0
  100. package/dist/tokens.cjs +29 -0
  101. package/dist/tokens.d.ts +13 -0
  102. package/dist/tokens.d.ts.map +1 -0
  103. package/dist/tokens.js +21 -0
  104. package/dist/tokens.mjs +8 -0
  105. package/dist/tsconfig.lib.tsbuildinfo +1 -0
  106. package/dist/types.cjs +33 -0
  107. package/dist/types.d.ts +239 -0
  108. package/dist/types.d.ts.map +1 -0
  109. package/dist/types.js +23 -0
  110. package/dist/types.mjs +12 -0
  111. package/dist/verify.cjs +724 -0
  112. package/dist/verify.d.ts +205 -0
  113. package/dist/verify.d.ts.map +1 -0
  114. package/dist/verify.js +371 -0
  115. package/dist/verify.mjs +590 -0
  116. package/package.json +121 -0
@@ -0,0 +1,104 @@
1
+ /**
2
+ * OAuth2 and OIDC for a Fluixi application.
3
+ *
4
+ * Two pieces, and the split is the point. `AuthClient` drives the protocol: it starts a
5
+ * login, turns a callback into tokens, refreshes and ends the session. `AuthService`
6
+ * drives the application: who is signed in, whether the session holds, what to render.
7
+ * The service depends on a client and never on which one, so the same application code
8
+ * runs whether the tokens live in the browser or on a server.
9
+ *
10
+ * ## Choosing a mode
11
+ *
12
+ * `tokens: 'browser'` is a public client with PKCE. No server is required, so it works for
13
+ * a static single-page deployment. A refresh token in storage is readable by any script
14
+ * on the page, which is the cost.
15
+ *
16
+ * `tokens: 'server'` keeps the tokens on the application's own server and gives the browser
17
+ * an httpOnly cookie. A script on the page has nothing to steal. It needs the routes
18
+ * from `@fluixi/oauth2/server`, so the app has to run a server.
19
+ *
20
+ * ## Wiring it
21
+ *
22
+ * ```ts
23
+ * // services/auth.ts
24
+ * export const auth = createAuthService<User>({
25
+ * config: {
26
+ * tokens: 'browser',
27
+ * issuer: 'https://localhost:8443',
28
+ * clientId: 'admin-spa',
29
+ * redirectUri: `${location.origin}/callback`,
30
+ * },
31
+ * });
32
+ *
33
+ * // entry-client.tsx
34
+ * provideRoot([{ provide: AuthServiceToken, useValue: auth }]);
35
+ *
36
+ * // anywhere below
37
+ * const auth = inject(AuthServiceToken);
38
+ * ```
39
+ *
40
+ * ## Binding a token to a key
41
+ *
42
+ * `dpop: true` stops a token being usable by whoever holds a copy. The provider records
43
+ * the key's thumbprint in the token, this client signs a proof for every request, and a
44
+ * service checks the two match. Okta turns the requirement on by default for a new client,
45
+ * so this is sometimes not optional.
46
+ *
47
+ * Both halves matter. A service that receives bound tokens must set `dpop: true` on its
48
+ * verifier as well, or it accepts them as though they were bearer tokens and the binding
49
+ * protects nothing.
50
+ *
51
+ * ## Where trust comes from
52
+ *
53
+ * This client does not verify token signatures, and that is deliberate rather than
54
+ * missing. Three things follow from it, and they are worth knowing before changing any
55
+ * of them.
56
+ *
57
+ * **The tokens are authentic by transport.** They arrive over a direct TLS call this
58
+ * client makes to the token endpoint, exchanging a code obtained with a PKCE verifier
59
+ * only this client holds. OIDC allows a client using the code flow to rely on that in
60
+ * place of checking the id token signature.
61
+ *
62
+ * **Identity comes from userinfo, not from reading a token.** The user is a round trip
63
+ * to the provider with the access token, so it is the provider's answer rather than a
64
+ * claim decoded here. Trusting a decoded id token for identity is the usual mistake, and
65
+ * it is why the userinfo subject is checked against the id token instead.
66
+ *
67
+ * **Verification belongs at the resource server.** An access token is a bearer credential
68
+ * for an API, opaque to the client by design. The API must check the signature, issuer,
69
+ * audience and expiry on every request, with the provider's JWKS. Discovery exposes
70
+ * `jwks_uri` on `Endpoints` for that, and an audited library such as `jose` should do the
71
+ * checking: algorithm confusion and `alg: none` are the standard ways a hand-written
72
+ * verifier becomes worse than none at all.
73
+ *
74
+ * A signature check added here would buy little: an attacker able to forge a token in
75
+ * this client's memory already controls the page, and a locally valid token says nothing
76
+ * about whether the session was revoked a minute ago.
77
+ *
78
+ * ## Hooks
79
+ *
80
+ * The hooks from `@fluixi/auth/client` take the service directly, because it satisfies
81
+ * the session shape they expect:
82
+ *
83
+ * ```ts
84
+ * export const { protectedRoute, useUser, Can } = createAuthHooks({
85
+ * session: auth,
86
+ * navigate: { handler: useNavigate },
87
+ * loginPath: '/login',
88
+ * });
89
+ * ```
90
+ */
91
+ export { createAuthService, paramsFromUrl } from './service.js';
92
+ export type { AuthService, AuthServiceOptions, AuthCredentials } from './service.js';
93
+ export { createBrowserClient } from './browser.js';
94
+ export { createServerClient, COOKIE_SESSION } from './server-client.js';
95
+ export { discover, clearDiscoveryCache } from './discovery.js';
96
+ export { createPkcePair, createVerifier, createChallenge, createStateValue, expiryFromJwt, } from './pkce.js';
97
+ export { createDpopKey, proofFor, thumbprintOf, boundKeyOf } from './dpop.js';
98
+ export type { DpopKey, ProofOptions } from './dpop.js';
99
+ export { safeReturnTo } from './return-to.js';
100
+ export type { ReturnToOptions } from './return-to.js';
101
+ export { OAuthError } from './types.js';
102
+ export type { AuthClient, AuthConfig, BaseConfig, BrowserConfig, CallbackParams, Endpoints, LoginOptions, ServerConfig, Tokens, } from './types.js';
103
+ export { AuthServiceToken, AuthClientToken } from './tokens.js';
104
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyFG;AACH,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAChE,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAErF,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAExE,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EACL,cAAc,EACd,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,aAAa,GACd,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC9E,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEtD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,YAAY,EACV,UAAU,EACV,UAAU,EACV,UAAU,EACV,aAAa,EACb,cAAc,EACd,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,MAAM,GACP,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,101 @@
1
+ /**
2
+ * OAuth2 and OIDC for a Fluixi application.
3
+ *
4
+ * Two pieces, and the split is the point. `AuthClient` drives the protocol: it starts a
5
+ * login, turns a callback into tokens, refreshes and ends the session. `AuthService`
6
+ * drives the application: who is signed in, whether the session holds, what to render.
7
+ * The service depends on a client and never on which one, so the same application code
8
+ * runs whether the tokens live in the browser or on a server.
9
+ *
10
+ * ## Choosing a mode
11
+ *
12
+ * `tokens: 'browser'` is a public client with PKCE. No server is required, so it works for
13
+ * a static single-page deployment. A refresh token in storage is readable by any script
14
+ * on the page, which is the cost.
15
+ *
16
+ * `tokens: 'server'` keeps the tokens on the application's own server and gives the browser
17
+ * an httpOnly cookie. A script on the page has nothing to steal. It needs the routes
18
+ * from `@fluixi/oauth2/server`, so the app has to run a server.
19
+ *
20
+ * ## Wiring it
21
+ *
22
+ * ```ts
23
+ * // services/auth.ts
24
+ * export const auth = createAuthService<User>({
25
+ * config: {
26
+ * tokens: 'browser',
27
+ * issuer: 'https://localhost:8443',
28
+ * clientId: 'admin-spa',
29
+ * redirectUri: `${location.origin}/callback`,
30
+ * },
31
+ * });
32
+ *
33
+ * // entry-client.tsx
34
+ * provideRoot([{ provide: AuthServiceToken, useValue: auth }]);
35
+ *
36
+ * // anywhere below
37
+ * const auth = inject(AuthServiceToken);
38
+ * ```
39
+ *
40
+ * ## Binding a token to a key
41
+ *
42
+ * `dpop: true` stops a token being usable by whoever holds a copy. The provider records
43
+ * the key's thumbprint in the token, this client signs a proof for every request, and a
44
+ * service checks the two match. Okta turns the requirement on by default for a new client,
45
+ * so this is sometimes not optional.
46
+ *
47
+ * Both halves matter. A service that receives bound tokens must set `dpop: true` on its
48
+ * verifier as well, or it accepts them as though they were bearer tokens and the binding
49
+ * protects nothing.
50
+ *
51
+ * ## Where trust comes from
52
+ *
53
+ * This client does not verify token signatures, and that is deliberate rather than
54
+ * missing. Three things follow from it, and they are worth knowing before changing any
55
+ * of them.
56
+ *
57
+ * **The tokens are authentic by transport.** They arrive over a direct TLS call this
58
+ * client makes to the token endpoint, exchanging a code obtained with a PKCE verifier
59
+ * only this client holds. OIDC allows a client using the code flow to rely on that in
60
+ * place of checking the id token signature.
61
+ *
62
+ * **Identity comes from userinfo, not from reading a token.** The user is a round trip
63
+ * to the provider with the access token, so it is the provider's answer rather than a
64
+ * claim decoded here. Trusting a decoded id token for identity is the usual mistake, and
65
+ * it is why the userinfo subject is checked against the id token instead.
66
+ *
67
+ * **Verification belongs at the resource server.** An access token is a bearer credential
68
+ * for an API, opaque to the client by design. The API must check the signature, issuer,
69
+ * audience and expiry on every request, with the provider's JWKS. Discovery exposes
70
+ * `jwks_uri` on `Endpoints` for that, and an audited library such as `jose` should do the
71
+ * checking: algorithm confusion and `alg: none` are the standard ways a hand-written
72
+ * verifier becomes worse than none at all.
73
+ *
74
+ * A signature check added here would buy little: an attacker able to forge a token in
75
+ * this client's memory already controls the page, and a locally valid token says nothing
76
+ * about whether the session was revoked a minute ago.
77
+ *
78
+ * ## Hooks
79
+ *
80
+ * The hooks from `@fluixi/auth/client` take the service directly, because it satisfies
81
+ * the session shape they expect:
82
+ *
83
+ * ```ts
84
+ * export const { protectedRoute, useUser, Can } = createAuthHooks({
85
+ * session: auth,
86
+ * navigate: { handler: useNavigate },
87
+ * loginPath: '/login',
88
+ * });
89
+ * ```
90
+ */
91
+ export { createAuthService, paramsFromUrl } from './service.js';
92
+ export { createBrowserClient } from './browser.js';
93
+ export { createServerClient, COOKIE_SESSION } from './server-client.js';
94
+ export { discover, clearDiscoveryCache } from './discovery.js';
95
+ export { createPkcePair, createVerifier, createChallenge, createStateValue, expiryFromJwt, } from './pkce.js';
96
+ export { createDpopKey, proofFor, thumbprintOf, boundKeyOf } from './dpop.js';
97
+ export { safeReturnTo } from './return-to.js';
98
+ export { OAuthError } from './types.js';
99
+ export { AuthServiceToken, AuthClientToken } from './tokens.js';
100
+ // Token verification lives on `@fluixi/oauth2/verify`, so a browser bundle never pulls in
101
+ // `jose` just because the package was imported.