@authgate/browser 0.3.0 → 0.4.0

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
@@ -24,7 +24,7 @@ framework-specific abstractions.
24
24
 
25
25
  - Read AuthGate CSRF token from browser cookies
26
26
  - Perform a CSRF-protected logout request
27
- - Explicit browser-side session refresh
27
+ - Explicit browser-side session refresh **with audience selection**
28
28
  - Optional `fetch` wrapper with **single-retry refresh semantics**
29
29
  - Clear success / failure signaling
30
30
  - Optional redirect on logout
@@ -57,7 +57,7 @@ It does not generate or validate it.
57
57
 
58
58
  ---
59
59
 
60
- ### Logout
60
+ ## Logout
61
61
 
62
62
  ```ts
63
63
  import { logout } from "@authgate/browser";
@@ -103,16 +103,28 @@ Redirecting is an optional side-effect and does **not** define success.
103
103
  ```ts
104
104
  import { refreshSession } from "@authgate/browser";
105
105
 
106
- const refreshed = await refreshSession();
106
+ const refreshed = await refreshSession("app");
107
107
  ```
108
108
 
109
109
  Attempts to refresh the current AuthGate session by calling:
110
110
 
111
- ```
111
+ ```text
112
112
  POST /auth/refresh
113
113
  ```
114
114
 
115
- Behavior:
115
+ with an explicit **audience declaration**.
116
+
117
+ ### Audience
118
+
119
+ The audience determines **which access token is minted** (e.g. `"app"`, `"admin"`).
120
+
121
+ - The client explicitly requests an audience
122
+ - AuthGate validates the requested audience against the user’s roles
123
+ - Requests for unauthorized audiences fail with `401`
124
+
125
+ If no audience is provided, `"app"` is used by default.
126
+
127
+ ### Behavior
116
128
 
117
129
  - Returns `true` if refresh succeeded
118
130
  - Returns `false` if refresh failed for any reason
@@ -141,16 +153,25 @@ const res = await authFetch("/api/data");
141
153
  `authFetch` is an **optional convenience wrapper** around `fetch` with
142
154
  AuthGate-aware refresh behavior.
143
155
 
144
- Behavior:
156
+ ### Behavior
145
157
 
146
158
  1. Performs the request with credentials
147
159
  2. If the response is **not `401`**, returns it directly
148
160
  3. If the response **is `401`**:
149
- - Attempts `refreshSession()`
161
+ - Attempts `refreshSession()` with the same audience
150
162
  - If refresh succeeds, retries the original request **once**
151
163
  - Otherwise, returns the original `401` response
152
164
 
153
- Important properties:
165
+ ### Audience-aware requests
166
+
167
+ ```ts
168
+ await authFetch("/admin/api/users", {}, { audience: "admin" });
169
+ ```
170
+
171
+ - The same audience is used for the refresh attempt
172
+ - Unauthorized audiences fail cleanly without retry loops
173
+
174
+ ### Important properties
154
175
 
155
176
  - At most **one retry**
156
177
  - No redirects
@@ -171,6 +192,16 @@ if (res.status === 401) {
171
192
  }
172
193
  ```
173
194
 
195
+ Admin request:
196
+
197
+ ```ts
198
+ const res = await authFetch(
199
+ "/admin/api/users",
200
+ {},
201
+ { audience: "admin" },
202
+ );
203
+ ```
204
+
174
205
  ---
175
206
 
176
207
  ## Security model
@@ -179,6 +210,7 @@ if (res.status === 401) {
179
210
  - CSRF validation is **enforced by AuthGate**
180
211
  - Refresh tokens are **never exposed to JavaScript**
181
212
  - All authentication state is owned by AuthGate
213
+ - Audiences are **explicitly requested and server-validated**
182
214
 
183
215
  This package only forwards existing browser state explicitly.
184
216
 
@@ -202,6 +234,7 @@ while preserving full application control.
202
234
  ## Compatibility
203
235
 
204
236
  - Works with any backend protected by AuthGate
237
+ - Supports SSR, SPA, and hybrid architectures
205
238
 
206
239
  ---
207
240
 
package/dist/index.d.ts CHANGED
@@ -38,27 +38,46 @@ export declare function logout(opts?: {
38
38
  redirectTo?: string;
39
39
  }): Promise<LogoutResult>;
40
40
  /**
41
- * authFetch performs a fetch request with AuthGate-aware refresh-once behavior.
41
+ * authFetch performs a fetch request with AuthGate-aware, refresh-once behavior
42
+ * for a specific audience.
42
43
  *
43
44
  * Behavior:
44
45
  * - Always includes credentials
45
- * - If the response is NOT 401 - returns it directly
46
+ * - Performs the initial request as-is
47
+ * - If the response is NOT 401, returns it directly
46
48
  * - If the response IS 401:
47
- * - Attempts POST /auth/refresh with CSRF
48
- * - If refresh succeeds - retries original request ONCE
49
- * - Otherwise - returns original 401 response
49
+ * - Attempts POST /auth/refresh with CSRF and the same requested audience
50
+ * - If refresh succeeds, retries the original request ONCE
51
+ * - If refresh fails, returns the original 401 response
52
+ *
53
+ * authFetch never redirects or mutates application state. Callers are expected
54
+ * to handle authentication failures explicitly.
55
+ *
56
+ * @param input The resource to fetch (same as `fetch`).
57
+ * @param init Optional fetch options. Credentials are always included.
58
+ * @param opts Optional AuthGate options.
59
+ * @param opts.audience The audience for which the request is made (e.g. "app", "admin").
60
+ * Defaults to "app".
61
+ * @returns The final `Response` from the original request or the retried request.
50
62
  */
51
- export declare function authFetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
63
+ export declare function authFetch(input: RequestInfo | URL, init?: RequestInit, opts?: {
64
+ audience?: string;
65
+ }): Promise<Response>;
52
66
  /**
53
- * refreshSession attempts to refresh the current AuthGate session.
67
+ * refreshSession attempts to refresh the current AuthGate session for a
68
+ * specific audience.
54
69
  *
55
70
  * It performs:
56
71
  * POST /auth/refresh
57
- * with CSRF protection and credentials
72
+ * with CSRF protection, credentials, and an explicit audience declaration.
73
+ *
74
+ * The server validates the requested audience against the user's roles and
75
+ * rejects the request if the audience is not permitted.
58
76
  *
59
- * The function:
60
- * - returns true if refresh succeeded
61
- * - returns false if refresh failed for any reason
77
+ * @param audience The audience for which a new access token should be minted.
78
+ * Defaults to "app".
79
+ * @returns `true` if the refresh succeeded, or `false` if refresh failed for
80
+ * any reason (unauthorized, expired session, or error).
62
81
  */
63
- export declare function refreshSession(): Promise<boolean>;
82
+ export declare function refreshSession(audience?: string): Promise<boolean>;
64
83
  export {};
package/dist/index.js CHANGED
@@ -68,22 +68,35 @@ export async function logout(opts) {
68
68
  return { ok: true };
69
69
  }
70
70
  /**
71
- * authFetch performs a fetch request with AuthGate-aware refresh-once behavior.
71
+ * authFetch performs a fetch request with AuthGate-aware, refresh-once behavior
72
+ * for a specific audience.
72
73
  *
73
74
  * Behavior:
74
75
  * - Always includes credentials
75
- * - If the response is NOT 401 - returns it directly
76
+ * - Performs the initial request as-is
77
+ * - If the response is NOT 401, returns it directly
76
78
  * - If the response IS 401:
77
- * - Attempts POST /auth/refresh with CSRF
78
- * - If refresh succeeds - retries original request ONCE
79
- * - Otherwise - returns original 401 response
79
+ * - Attempts POST /auth/refresh with CSRF and the same requested audience
80
+ * - If refresh succeeds, retries the original request ONCE
81
+ * - If refresh fails, returns the original 401 response
82
+ *
83
+ * authFetch never redirects or mutates application state. Callers are expected
84
+ * to handle authentication failures explicitly.
85
+ *
86
+ * @param input The resource to fetch (same as `fetch`).
87
+ * @param init Optional fetch options. Credentials are always included.
88
+ * @param opts Optional AuthGate options.
89
+ * @param opts.audience The audience for which the request is made (e.g. "app", "admin").
90
+ * Defaults to "app".
91
+ * @returns The final `Response` from the original request or the retried request.
80
92
  */
81
- export async function authFetch(input, init = {}) {
93
+ export async function authFetch(input, init = {}, opts) {
94
+ const audience = opts?.audience ?? "app";
82
95
  const res = await fetch(input, withCredentials(init));
83
96
  if (res.status !== 401) {
84
97
  return res;
85
98
  }
86
- const refreshed = await refreshSession();
99
+ const refreshed = await refreshSession(audience);
87
100
  if (!refreshed) {
88
101
  return res;
89
102
  }
@@ -96,24 +109,29 @@ function withCredentials(init) {
96
109
  };
97
110
  }
98
111
  /**
99
- * refreshSession attempts to refresh the current AuthGate session.
112
+ * refreshSession attempts to refresh the current AuthGate session for a
113
+ * specific audience.
100
114
  *
101
115
  * It performs:
102
116
  * POST /auth/refresh
103
- * with CSRF protection and credentials
117
+ * with CSRF protection, credentials, and an explicit audience declaration.
118
+ *
119
+ * The server validates the requested audience against the user's roles and
120
+ * rejects the request if the audience is not permitted.
104
121
  *
105
- * The function:
106
- * - returns true if refresh succeeded
107
- * - returns false if refresh failed for any reason
122
+ * @param audience The audience for which a new access token should be minted.
123
+ * Defaults to "app".
124
+ * @returns `true` if the refresh succeeded, or `false` if refresh failed for
125
+ * any reason (unauthorized, expired session, or error).
108
126
  */
109
- export async function refreshSession() {
127
+ export async function refreshSession(audience = "app") {
110
128
  const csrf = getCSRFToken();
111
129
  if (!csrf) {
112
130
  return false;
113
131
  }
114
132
  let res;
115
133
  try {
116
- res = await fetch("/auth/refresh", {
134
+ res = await fetch(`/auth/refresh?audience=${encodeURIComponent(audience)}`, {
117
135
  method: "POST",
118
136
  headers: {
119
137
  "X-CSRF-Token": csrf,
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "type": "git",
5
5
  "url": "https://github.com/alexlup06-authgate/authgate-browser.git"
6
6
  },
7
- "version": "0.3.0",
7
+ "version": "0.4.0",
8
8
  "description": "Browser-side helpers for AuthGate (logout, CSRF forwarding)",
9
9
  "license": "MIT",
10
10
  "type": "module",