@lpshanley/oidc-start-react 0.4.0 → 0.4.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 (2) hide show
  1. package/README.md +37 -1
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -184,6 +184,29 @@ beforeLoad: ({ location }) => requireAuth({ signInPath: '/sign-in', returnPathna
184
184
 
185
185
  The helper reads the session on the server. A guest follows a document redirect to the sign-in route. A signed-in user is available as `Route.useRouteContext().user`. Enforce authorization in every server function or endpoint that serves private data, including those called by the guarded route.
186
186
 
187
+ ### Restrict an admin route by role
188
+
189
+ Import `requireAuth` from `@lpshanley/oidc-start-react/functions`, `hasRole` from the package root, and `redirect` from `@tanstack/react-router`. Compose them in the admin route's `beforeLoad`.
190
+
191
+ ```ts
192
+ beforeLoad: async ({ location }) => {
193
+ const { user } = await requireAuth({ signInPath: '/sign-in', returnPathname: location.href })
194
+ if (!hasRole(user, 'admin')) throw redirect({ href: '/forbidden', reloadDocument: true })
195
+ return { user }
196
+ }
197
+ ```
198
+
199
+ Guests sign in and return to the requested URL. An admin sees the dashboard. A signed-in user without the role goes to the app's `/forbidden` endpoint, which returns HTTP 403. Use role names from your provider's configured roles claim. [Admin route](https://github.com/lpshanley/oidc-start/blob/main/examples/tanstack-start/src/routes/admin.tsx) · [Forbidden response](https://github.com/lpshanley/oidc-start/blob/main/examples/tanstack-start/src/routes/forbidden.ts)
200
+
201
+ Private endpoints must also check the current request before reading admin data or performing a mutation. In a server route handler, import `getOidcContext` from `@lpshanley/oidc-start-react/server` and check the resolved user.
202
+
203
+ ```ts
204
+ const { user } = getOidcContext().auth()
205
+ if (!user) return new Response(null, { status: 401 })
206
+ if (!hasRole(user, 'admin')) return new Response(null, { status: 403 })
207
+ // Perform the authorized operation here.
208
+ ```
209
+
187
210
  ### Customize callback failures
188
211
 
189
212
  Pass `onError({ reason, request })` to `handleCallbackRoute` to return a custom response. It takes precedence over `errorRedirectUrl`. A provider cancellation is `access_denied`, and a missing verifier (for example after its cookie expires) is `sign_in_expired`. Other reasons are `invalid_callback`, `invalid_state`, `provider_error`, `token_exchange_failed`, and `session_failed`. The middleware still clears the failed flow's verifier. A rejection by your own `allowSession` policy takes its separate 403 path.
@@ -202,7 +225,20 @@ GET: handleCallbackRoute({
202
225
  })
203
226
  ```
204
227
 
205
- On that page, import `authErrorMessage` from `@lpshanley/oidc-start-react`. Read `auth_error` from the route's search parameters and render `<p role="alert">{authErrorMessage(auth_error)}</p>` when the parameter is present. The helper selects fixed messages and gives unknown values a generic retry message. Host access denials keep their 403 response.
228
+ On the login page, read `auth_error` with `Route.useSearch()`. When the parameter is present, render `<p role="alert">{authErrorMessage(auth_error)}</p>` using `authErrorMessage` from `@lpshanley/oidc-start-react`. Unknown values receive a generic retry message. Host access denials keep their 403 response.
229
+
230
+ Keep the message visible until the user chooses **Dismiss**. Inside the login component, bind `const navigate = Route.useNavigate()` and use this click handler. It removes only the error parameter, preserves the fragment and replaces the current history entry so Back returns to the preceding page.
231
+
232
+ ```tsx
233
+ <button onClick={() => navigate({
234
+ search: previous => ({ ...previous, auth_error: undefined }),
235
+ hash: true,
236
+ replace: true,
237
+ resetScroll: false,
238
+ })}>Dismiss</button>
239
+ ```
240
+
241
+ The working example wires the callback to the login page and includes the route's search validation. [Callback](https://github.com/lpshanley/oidc-start/blob/main/examples/tanstack-start/src/routes/callback.ts) · [Dismissible login error](https://github.com/lpshanley/oidc-start/blob/main/examples/tanstack-start/src/routes/login.tsx)
206
242
 
207
243
  ### Require a recent login
208
244
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lpshanley/oidc-start-react",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -40,7 +40,7 @@
40
40
  "node": ">=22.12.0"
41
41
  },
42
42
  "dependencies": {
43
- "@lpshanley/oidc-start-core": "0.4.0",
43
+ "@lpshanley/oidc-start-core": "0.4.1",
44
44
  "zod": "4.6.7"
45
45
  },
46
46
  "devDependencies": {