Skip to content

Commit 15709d0

Browse files
committed
feat: introduce Riligar Auth skills for React and Elysia, including documentation, code snippets, and setup guides.
1 parent 574440d commit 15709d0

File tree

10 files changed

+501
-0
lines changed

10 files changed

+501
-0
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
---
2+
name: riligar-dev-auth-elysia
3+
description: 'Comprehensive guide for integrating the Riligar Auth Elysia SDK into backend servers. Use when a user needs to: (1) Set up a backend auth plugin, (2) Configure Elysia with Riligar Secret Key, (3) Protect API routes or groups, (4) Access authenticated user data in handlers, (5) Perform manual JWT verification.'
4+
---
5+
6+
# Riligar Auth Elysia Skill
7+
8+
This skill provides a backend workflow for integrating authentication and permissions using the `@riligar/auth-elysia` SDK.
9+
10+
## Core Integration Workflow
11+
12+
### 1. Installation
13+
14+
Install the backend SDK:
15+
16+
```bash
17+
npm install @riligar/auth-elysia
18+
```
19+
20+
### 2. Environment Variables
21+
22+
Set up your Secret Key and URLs in your `.env` file.
23+
24+
> [!CAUTION]
25+
> Backend integration requires the **Secret Key** (`sk_...`). Never share this key or include it in client-side code.
26+
27+
```bash
28+
# .env
29+
AUTH_API_URL=https://manager.myauth.click
30+
AUTH_API_SECRET=sk_live_your_secret_key
31+
AUTH_JWKS_URL=https://manager.myauth.click/.well-known/jwks.json
32+
```
33+
34+
### 3. Plugin Registration
35+
36+
Add the `authPlugin` to your Elysia instance.
37+
38+
```typescript
39+
import { Elysia } from 'elysia'
40+
import { authPlugin } from '@riligar/auth-elysia'
41+
42+
const app = new Elysia()
43+
.use(
44+
authPlugin({
45+
apiUrl: process.env.AUTH_API_URL,
46+
apiKey: process.env.AUTH_API_SECRET,
47+
jwksUrl: process.env.AUTH_JWKS_URL,
48+
})
49+
)
50+
.listen(3000)
51+
```
52+
53+
For more patterns, see [server-snippets.ts](assets/server-snippets.ts).
54+
55+
## Specialized Guides
56+
57+
- **Context & User Data**: Documentation for `ctx.auth` and `ctx.user`. See [context-and-user.md](references/context-and-user.md).
58+
- **Route Protection**: How to implement `requireAuth` middleware and guard route groups. See [route-protection.md](references/route-protection.md).
59+
- **Manual Verification**: Using `verifyToken` for custom JWT handling. See [manual-verification.md](references/manual-verification.md).
60+
61+
## Common Tasks
62+
63+
### Protecting a Route Group
64+
65+
Use `onBeforeHandle` to secure multiple endpoints efficiently.
66+
67+
```typescript
68+
app.group('/api/v1', app => app.onBeforeHandle(requireAuth).get('/data', () => ({ ok: true })))
69+
```
70+
71+
### Accessing User Profile
72+
73+
Access the decoded user data directly from the context.
74+
75+
```typescript
76+
app.get('/profile', ({ user }) => {
77+
return { id: user.id, email: user.email }
78+
})
79+
```
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Server Snippets for Elysia
2+
3+
// 1. Core Server with Auth Plugin
4+
export const fullServerSetup = `
5+
import { Elysia } from 'elysia'
6+
import { authPlugin } from '@riligar/auth-elysia'
7+
8+
const app = new Elysia()
9+
.use(authPlugin({
10+
apiUrl: process.env.AUTH_API_URL, // https://manager.myauth.click
11+
apiKey: process.env.AUTH_API_SECRET, // sk_live_...
12+
jwksUrl: process.env.AUTH_JWKS_URL, // .well-known/jwks.json
13+
}))
14+
.get('/public', () => 'Hello World')
15+
.get('/private', ({ auth, user }) => {
16+
if (!auth.isAuthenticated) return 'Unauthorized'
17+
return \`Hello \${user.name}\`
18+
})
19+
.listen(3000)
20+
`
21+
22+
// 2. Auth Middleware
23+
export const middlewareSnippet = `
24+
export const requireAuth = ({ auth, set }) => {
25+
if (!auth.isAuthenticated) {
26+
set.status = 401
27+
return { error: 'Unauthorized' }
28+
}
29+
}
30+
31+
// Usage: app.get('/protected', requireAuth, () => 'Secret Area')
32+
`
33+
34+
// 3. User Data access
35+
export const userAccessSnippet = `
36+
app.get('/me', ({ auth, user }) => {
37+
if (!auth.isAuthenticated) return { error: 'Not logged in' }
38+
39+
return {
40+
id: user.id,
41+
email: user.email,
42+
verified: user.emailVerified
43+
}
44+
})
45+
`
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Auth Context and User Object
2+
3+
The `@riligar/auth-elysia` plugin decorates the Elysia context with `auth` and `user` objects.
4+
5+
## Auth Object (`ctx.auth`)
6+
7+
Provides metadata about the current request's authentication state.
8+
9+
| Property | Type | Description |
10+
| :--------------------- | :----------------- | :----------------------------------------------- |
11+
| `auth.isAuthenticated` | `boolean` | `true` if a valid JWT was found and verified. |
12+
| `auth.token` | `string \| null` | The raw JWT token from the Authorization header. |
13+
| `auth.error` | `string \| null` | Error message if verification failed. |
14+
| `auth.verify()` | `Promise<boolean>` | Manually triggers token verification. |
15+
16+
## User Object (`ctx.user`)
17+
18+
Contains the decoded payload from the JWT. Only populated if `isAuthenticated` is `true`.
19+
20+
| Property | Type | Description |
21+
| :------------------- | :-------- | :------------------------------------------------ |
22+
| `user.id` | `string` | Unique identifier of the user (from `sub` claim). |
23+
| `user.email` | `string` | User's email address. |
24+
| `user.name` | `string` | User's display name. |
25+
| `user.emailVerified` | `boolean` | Whether the user's email has been verified. |
26+
| `user.metadata` | `object` | Custom metadata associated with the user account. |
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Manual Token Verification
2+
3+
In some cases, you may need to verify a JWT manually outside of the standard `authPlugin` context (e.g., in a background job, cron, or a custom WebSocket handler).
4+
5+
## Using `verifyToken`
6+
7+
The SDK exports a `verifyToken` function that handles the full JWKS verification flow.
8+
9+
```typescript
10+
import { verifyToken } from '@riligar/auth-elysia'
11+
12+
async function customHandler(token: string) {
13+
try {
14+
const payload = await verifyToken(token, {
15+
jwksUrl: process.env.AUTH_JWKS_URL,
16+
// optional: issuer, audience verification
17+
})
18+
19+
console.log('Valid user:', payload.sub)
20+
return payload
21+
} catch (error) {
22+
console.error('Verification failed:', error.message)
23+
throw new Error('Unauthorized')
24+
}
25+
}
26+
```
27+
28+
## JWKS Caching
29+
30+
The `verifyToken` function automatically caches the JWKS keys to avoid unnecessary network requests. If you need to force a refresh (e.g., after a key rotation), use `refreshJwks`:
31+
32+
```typescript
33+
import { refreshJwks } from '@riligar/auth-elysia'
34+
35+
await refreshJwks(process.env.AUTH_JWKS_URL)
36+
```
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Route Protection and Middleware
2+
3+
Effective patterns for securing your Elysia API routes.
4+
5+
## Recommended Middleware Pattern
6+
7+
Create a reusable `requireAuth` helper to enforce authentication on specific endpoints.
8+
9+
```typescript
10+
const requireAuth = ({ auth, set }) => {
11+
if (!auth.isAuthenticated) {
12+
set.status = 401
13+
return { error: 'Unauthorized: Missing or invalid token' }
14+
}
15+
}
16+
```
17+
18+
## Applying Protection
19+
20+
### To a single route
21+
22+
```typescript
23+
app.get('/me', requireAuth, ({ user }) => {
24+
return { name: user.name }
25+
})
26+
```
27+
28+
### To a group of routes
29+
30+
Use `onBeforeHandle` to protect an entire API section.
31+
32+
```typescript
33+
app.group('/api/admin', app =>
34+
app
35+
.onBeforeHandle(requireAuth)
36+
.get('/dashboard', () => ({ stats: '...' }))
37+
.post('/settings', () => ({ saved: true }))
38+
)
39+
```
40+
41+
## Permission-Based access (RBAC)
42+
43+
You can extend the middleware to check for specific roles or permissions.
44+
45+
```typescript
46+
const requireAdmin = ({ auth, user, set }) => {
47+
if (!auth.isAuthenticated || user.role !== 'admin') {
48+
set.status = 403
49+
return { error: 'Forbidden' }
50+
}
51+
}
52+
```
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
---
2+
name: riligar-dev-auth-react
3+
description: 'Comprehensive guide for integrating the Riligar Auth React SDK into web applications. Use when a user needs to: (1) Set up authentication from scratch, (2) Configure AuthProvider, (3) Implement route protection, (4) Use auth hooks or pre-built UI components, (5) Handle login/signup/profile/magic links in React.'
4+
---
5+
6+
# Riligar Auth React Skill
7+
8+
This skill provides a complete workflow for integrating authentication and permissions using the `@riligar/auth-react` SDK.
9+
10+
## Core Integration Workflow
11+
12+
### 1. Installation
13+
14+
Install the SDK using bun (preferred) or npm:
15+
16+
```bash
17+
bun add @riligar/auth-react
18+
```
19+
20+
### 2. Environment Variables
21+
22+
Set up your Public Key in your `.env.local` file.
23+
24+
> [!IMPORTANT]
25+
> Always use the **Public Key** (`pk_...`) in the frontend. Never expose your Secret Key.
26+
27+
```bash
28+
# .env.local
29+
VITE_AUTH_API_KEY=pk_live_your_public_key
30+
```
31+
32+
### 3. AuthProvider Setup
33+
34+
Wrap your application (usually in `main.jsx` or `App.jsx`) with the `AuthProvider`.
35+
36+
```jsx
37+
import { AuthProvider } from '@riligar/auth-react'
38+
39+
ReactDOM.createRoot(document.getElementById('root')).render(
40+
<AuthProvider apiKey={import.meta.env.VITE_AUTH_API_KEY}>
41+
<App />
42+
</AuthProvider>
43+
)
44+
```
45+
46+
For more setup patterns, see [setup-snippets.js](assets/setup-snippets.js).
47+
48+
## Specialized Guides
49+
50+
- **Hooks & UI Components**: Comprehensive list of `useAuth`, `useSignIn`, and pre-built Mantine components. See [hooks-and-components.md](references/hooks-and-components.md).
51+
- **Route Protection**: How to use `<Protect />`, `<SignedIn>`, and active route guards. See [route-protection.md](references/route-protection.md).
52+
- **Core Concepts**: Understanding B2C/B2B models and API key security. See [concepts.md](references/concepts.md).
53+
54+
## Common Tasks
55+
56+
### Checking Auth State
57+
58+
Use `useAuth()` to access user data and authentication status.
59+
60+
```jsx
61+
const { user, isAuthenticated, loading } = useAuth()
62+
```
63+
64+
### Adding a Login Form
65+
66+
Simply drop the `<SignIn />` component. Use `variant="modal"` if you want it in a popup.
67+
68+
```jsx
69+
<SignIn />
70+
// or
71+
<SignIn variant="modal" opened={isOpen} onClose={() => setIsOpen(false)} />
72+
```
73+
74+
### Protecting a Dashboard
75+
76+
Wrap your sub-routes with `<Protect />`.
77+
78+
```jsx
79+
<Route element={<Protect redirectTo="/login" />}>
80+
<Route
81+
path="/dashboard"
82+
element={<Dashboard />}
83+
/>
84+
</Route>
85+
```
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Setup Snippets
2+
3+
// 1. main.jsx / index.jsx setup
4+
export const authProviderSetup = `
5+
import { AuthProvider } from '@riligar/auth-react';
6+
7+
ReactDOM.createRoot(document.getElementById('root')).render(
8+
<React.StrictMode>
9+
<AuthProvider apiKey={import.meta.env.VITE_AUTH_API_KEY}>
10+
<App />
11+
</AuthProvider>
12+
</React.StrictMode>
13+
);
14+
`
15+
16+
// 2. Protected Routes setup
17+
export const protectedRoutesSnippet = `
18+
import { Protect, SignIn } from '@riligar/auth-react';
19+
import { BrowserRouter, Routes, Route } from 'react-router-dom';
20+
21+
function AppRoutes() {
22+
return (
23+
<BrowserRouter>
24+
<Routes>
25+
<Route path="/signin" element={<SignIn />} />
26+
27+
<Route element={<Protect redirectTo="/signin" />}>
28+
<Route path="/" element={<Dashboard />} />
29+
<Route path="/profile" element={<Profile />} />
30+
</Route>
31+
</Routes>
32+
</BrowserRouter>
33+
);
34+
}
35+
`
36+
37+
// 3. User State hook
38+
export const useAuthExample = `
39+
import { useAuth } from '@riligar/auth-react';
40+
41+
function UserButton() {
42+
const { user, isAuthenticated, signOut } = useAuth();
43+
44+
if (!isAuthenticated) return null;
45+
46+
return (
47+
<button onClick={signOut}>
48+
Log out {user.name}
49+
</button>
50+
);
51+
}
52+
`

0 commit comments

Comments
 (0)