@notoofly/auth-server 1.0.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/CHANGELOG.md +35 -0
- package/LICENSE +21 -0
- package/README.md +307 -0
- package/dist/adapters/elysia/index.d.ts +3 -0
- package/dist/adapters/elysia/index.d.ts.map +1 -0
- package/dist/adapters/elysia/index.js +2 -0
- package/dist/adapters/elysia/index.js.map +1 -0
- package/dist/adapters/elysia/plugin.d.ts +163 -0
- package/dist/adapters/elysia/plugin.d.ts.map +1 -0
- package/dist/adapters/elysia/plugin.js +146 -0
- package/dist/adapters/elysia/plugin.js.map +1 -0
- package/dist/adapters/express/index.d.ts +3 -0
- package/dist/adapters/express/index.d.ts.map +1 -0
- package/dist/adapters/express/index.js +2 -0
- package/dist/adapters/express/index.js.map +1 -0
- package/dist/adapters/express/middleware.d.ts +14 -0
- package/dist/adapters/express/middleware.d.ts.map +1 -0
- package/dist/adapters/express/middleware.js +156 -0
- package/dist/adapters/express/middleware.js.map +1 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +2 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/jwt-verifier.d.ts +16 -0
- package/dist/core/jwt-verifier.d.ts.map +1 -0
- package/dist/core/jwt-verifier.js +117 -0
- package/dist/core/jwt-verifier.js.map +1 -0
- package/dist/types/auth-user.d.ts +12 -0
- package/dist/types/auth-user.d.ts.map +1 -0
- package/dist/types/auth-user.js +2 -0
- package/dist/types/auth-user.js.map +1 -0
- package/dist/types/index.d.ts +40 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +19 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/authorization.d.ts +9 -0
- package/dist/utils/authorization.d.ts.map +1 -0
- package/dist/utils/authorization.js +33 -0
- package/dist/utils/authorization.js.map +1 -0
- package/dist/utils/security.d.ts +31 -0
- package/dist/utils/security.d.ts.map +1 -0
- package/dist/utils/security.js +55 -0
- package/dist/utils/security.js.map +1 -0
- package/dist/utils/token-extraction.d.ts +3 -0
- package/dist/utils/token-extraction.d.ts.map +1 -0
- package/dist/utils/token-extraction.js +24 -0
- package/dist/utils/token-extraction.js.map +1 -0
- package/package.json +87 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2024-04-05
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Initial production release
|
|
12
|
+
- JWT verification with JWKS caching
|
|
13
|
+
- Express.js middleware adapter
|
|
14
|
+
- Elysia framework adapter
|
|
15
|
+
- Role-based authorization guards
|
|
16
|
+
- Permission-based authorization guards
|
|
17
|
+
- Race-safe JWKS fetching
|
|
18
|
+
- TypeScript support with strict typing
|
|
19
|
+
- Comprehensive error handling
|
|
20
|
+
|
|
21
|
+
### Security
|
|
22
|
+
- Token validation with issuer and audience verification
|
|
23
|
+
- Secure caching with TTL
|
|
24
|
+
- Input validation and sanitization
|
|
25
|
+
- Error message sanitization
|
|
26
|
+
|
|
27
|
+
### Performance
|
|
28
|
+
- In-memory JWKS caching
|
|
29
|
+
- Deduplicated concurrent requests
|
|
30
|
+
- Optimized token verification
|
|
31
|
+
|
|
32
|
+
### Documentation
|
|
33
|
+
- Complete API documentation
|
|
34
|
+
- Usage examples
|
|
35
|
+
- Migration guide
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Notoofly Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
# @notoofly/auth-server
|
|
2
|
+
|
|
3
|
+
Production-ready JWT verification and authorization middleware for Node.js applications.
|
|
4
|
+
|
|
5
|
+
## 🚀 Features
|
|
6
|
+
|
|
7
|
+
- **JWT Verification**: Secure token validation with JWKS caching
|
|
8
|
+
- **Framework Adapters**: Native support for Express.js and Elysia
|
|
9
|
+
- **Authorization**: Role-based and permission-based access control
|
|
10
|
+
- **Security**: Race-safe fetching, input validation, error sanitization
|
|
11
|
+
- **Performance**: In-memory caching with configurable TTL
|
|
12
|
+
- **TypeScript**: Full type safety with strict typing
|
|
13
|
+
|
|
14
|
+
## 📦 Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @notoofly/auth-server
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 🔧 Quick Start
|
|
21
|
+
|
|
22
|
+
### Express.js Integration
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import express from 'express';
|
|
26
|
+
import { createAuthMiddleware, createRoleGuard } from '@notoofly/auth-server/express';
|
|
27
|
+
|
|
28
|
+
const app = express();
|
|
29
|
+
|
|
30
|
+
// Configure authentication middleware
|
|
31
|
+
const authMiddleware = createAuthMiddleware({
|
|
32
|
+
jwksUri: 'https://your-auth-domain.com/.well-known/jwks.json',
|
|
33
|
+
issuer: 'https://your-auth-domain.com',
|
|
34
|
+
audience: 'your-api',
|
|
35
|
+
cacheTtl: 300000, // 5 minutes
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Apply authentication to routes
|
|
39
|
+
app.use('/api', authMiddleware);
|
|
40
|
+
|
|
41
|
+
// Protected route with role guard
|
|
42
|
+
app.get('/api/admin', createRoleGuard('admin'), (req, res) => {
|
|
43
|
+
res.json({ message: 'Admin access granted' });
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
app.listen(3000);
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Elysia Integration
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { Elysia } from 'elysia';
|
|
53
|
+
import { createAuthPlugin, createRoleGuard } from '@notoofly/auth-server/elysia';
|
|
54
|
+
|
|
55
|
+
const app = new Elysia()
|
|
56
|
+
.use(createAuthPlugin({
|
|
57
|
+
jwksUri: 'https://your-auth-domain.com/.well-known/jwks.json',
|
|
58
|
+
issuer: 'https://your-auth-domain.com',
|
|
59
|
+
audience: 'your-api',
|
|
60
|
+
}))
|
|
61
|
+
.guard(
|
|
62
|
+
{ role: 'admin' },
|
|
63
|
+
({ user }) => ({ message: `Hello admin ${user.email}` })
|
|
64
|
+
)
|
|
65
|
+
.listen(3000);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## ⚙️ Configuration
|
|
69
|
+
|
|
70
|
+
### Environment Variables
|
|
71
|
+
|
|
72
|
+
Create a `.env` file based on `.env.example`:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# JWT Configuration
|
|
76
|
+
JWT_ISSUER=https://your-auth-domain.com
|
|
77
|
+
JWT_AUDIENCE=your-api-audience
|
|
78
|
+
JWKS_URI=https://your-auth-domain.com/.well-known/jwks.json
|
|
79
|
+
JWKS_CACHE_TTL=300000
|
|
80
|
+
|
|
81
|
+
# Security
|
|
82
|
+
NODE_ENV=production
|
|
83
|
+
LOG_LEVEL=info
|
|
84
|
+
ALLOWED_ORIGINS=https://yourdomain.com,https://app.yourdomain.com
|
|
85
|
+
|
|
86
|
+
# Rate Limiting
|
|
87
|
+
RATE_LIMIT_WINDOW_MS=60000
|
|
88
|
+
RATE_LIMIT_MAX_REQUESTS=100
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Configuration Options
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
interface JwtVerificationConfig {
|
|
95
|
+
jwksUri: string; // JWKS endpoint URL
|
|
96
|
+
issuer: string; // Expected token issuer
|
|
97
|
+
audience: string; // Expected token audience
|
|
98
|
+
cacheTtl?: number; // Cache TTL in milliseconds (default: 300000)
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## 🛡️ Security Features
|
|
103
|
+
|
|
104
|
+
### Token Validation
|
|
105
|
+
- **Algorithm Support**: RS256 and ES256
|
|
106
|
+
- **Claims Verification**: iss, aud, exp, nbf
|
|
107
|
+
- **Key Validation**: Kid matching and key rotation support
|
|
108
|
+
|
|
109
|
+
### Caching Strategy
|
|
110
|
+
- **Race-Safe**: Deduplicated concurrent requests
|
|
111
|
+
- **Memory Efficient**: Automatic cleanup of expired keys
|
|
112
|
+
- **Configurable TTL**: Default 5 minutes
|
|
113
|
+
|
|
114
|
+
### Error Handling
|
|
115
|
+
- **Sanitized Messages**: Production-safe error responses
|
|
116
|
+
- **Structured Logging**: Consistent error format
|
|
117
|
+
- **Graceful Degradation**: Fallback for JWKS unavailability
|
|
118
|
+
|
|
119
|
+
## 📚 API Reference
|
|
120
|
+
|
|
121
|
+
### Core Classes
|
|
122
|
+
|
|
123
|
+
#### JwtVerifier
|
|
124
|
+
|
|
125
|
+
Main JWT verification class.
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
import { JwtVerifier } from '@notoofly/auth-server';
|
|
129
|
+
|
|
130
|
+
const verifier = new JwtVerifier({
|
|
131
|
+
jwksUri: 'https://your-auth-domain.com/.well-known/jwks.json',
|
|
132
|
+
issuer: 'https://your-auth-domain.com',
|
|
133
|
+
audience: 'your-api',
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// Verify access token
|
|
137
|
+
const user = await verifier.verifyAccessToken(token);
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
#### Methods
|
|
141
|
+
|
|
142
|
+
- `verifyAccessToken(token: string): Promise<AuthUser>`
|
|
143
|
+
- `getUserFromToken(token: string): Promise<AuthUser>`
|
|
144
|
+
|
|
145
|
+
### Authorization Utilities
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
import {
|
|
149
|
+
hasRole,
|
|
150
|
+
hasPermission,
|
|
151
|
+
hasAllRoles,
|
|
152
|
+
hasAnyPermission,
|
|
153
|
+
checkGuard
|
|
154
|
+
} from '@notoofly/auth-server';
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Express Middleware
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
import {
|
|
161
|
+
createAuthMiddleware,
|
|
162
|
+
createRoleGuard,
|
|
163
|
+
createPermissionGuard,
|
|
164
|
+
createGuard
|
|
165
|
+
} from '@notoofly/auth-server/express';
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Elysia Plugin
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import {
|
|
172
|
+
createAuthPlugin,
|
|
173
|
+
createRoleGuard,
|
|
174
|
+
createPermissionGuard,
|
|
175
|
+
createGuard
|
|
176
|
+
} from '@notoofly/auth-server/elysia';
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## 🔒 Best Practices
|
|
180
|
+
|
|
181
|
+
### Production Deployment
|
|
182
|
+
|
|
183
|
+
1. **Environment Configuration**
|
|
184
|
+
```bash
|
|
185
|
+
NODE_ENV=production
|
|
186
|
+
LOG_LEVEL=error
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
2. **Security Headers**
|
|
190
|
+
```typescript
|
|
191
|
+
// Middleware automatically adds security headers
|
|
192
|
+
app.use(helmet());
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
3. **Rate Limiting**
|
|
196
|
+
```typescript
|
|
197
|
+
// Configure rate limiting
|
|
198
|
+
const rateLimit = rateLimit({
|
|
199
|
+
windowMs: 60000,
|
|
200
|
+
max: 100
|
|
201
|
+
});
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
4. **Monitoring**
|
|
205
|
+
```typescript
|
|
206
|
+
// Add request logging
|
|
207
|
+
app.use((req, res, next) => {
|
|
208
|
+
console.log(`${req.method} ${req.path}`, {
|
|
209
|
+
ip: req.ip,
|
|
210
|
+
userAgent: req.get('User-Agent')
|
|
211
|
+
});
|
|
212
|
+
next();
|
|
213
|
+
});
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Security Considerations
|
|
217
|
+
|
|
218
|
+
- **HTTPS Only**: Always use HTTPS in production
|
|
219
|
+
- **CORS Configuration**: Configure allowed origins properly
|
|
220
|
+
- **Key Rotation**: Regularly rotate JWT signing keys
|
|
221
|
+
- **Token Expiration**: Use short-lived access tokens
|
|
222
|
+
- **Error Messages**: Don't expose sensitive information
|
|
223
|
+
|
|
224
|
+
## 🧪 Testing
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
# Run tests
|
|
228
|
+
npm test
|
|
229
|
+
|
|
230
|
+
# Run tests with coverage
|
|
231
|
+
npm run test:ci
|
|
232
|
+
|
|
233
|
+
# Type checking
|
|
234
|
+
npm run type-check
|
|
235
|
+
|
|
236
|
+
# Linting
|
|
237
|
+
npm run lint
|
|
238
|
+
npm run lint:fix
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## 📈 Performance
|
|
242
|
+
|
|
243
|
+
### Benchmarks
|
|
244
|
+
- **JWT Verification**: <1ms average
|
|
245
|
+
- **JWKS Caching**: 99% hit rate
|
|
246
|
+
- **Memory Usage**: <10MB for 1000 cached keys
|
|
247
|
+
- **Concurrent Requests**: No race conditions
|
|
248
|
+
|
|
249
|
+
### Optimization Tips
|
|
250
|
+
|
|
251
|
+
1. **Cache TTL**: Balance between freshness and performance
|
|
252
|
+
2. **Connection Pooling**: Reuse HTTP connections
|
|
253
|
+
3. **Memory Monitoring**: Monitor cache size
|
|
254
|
+
4. **Load Balancing**: Distribute across multiple instances
|
|
255
|
+
|
|
256
|
+
## 🔄 Migration
|
|
257
|
+
|
|
258
|
+
### From v0.x to v1.0
|
|
259
|
+
|
|
260
|
+
Breaking changes:
|
|
261
|
+
- Package renamed to `@notoofly/auth-server`
|
|
262
|
+
- TypeScript exports now use `.js` extensions
|
|
263
|
+
- Configuration options updated
|
|
264
|
+
|
|
265
|
+
### Migration Steps
|
|
266
|
+
|
|
267
|
+
1. Update package.json:
|
|
268
|
+
```json
|
|
269
|
+
{
|
|
270
|
+
"dependencies": {
|
|
271
|
+
"@notoofly/auth-server": "^1.0.0"
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
2. Update imports:
|
|
277
|
+
```typescript
|
|
278
|
+
// Before
|
|
279
|
+
import { JwtVerifier } from 'auth-server';
|
|
280
|
+
|
|
281
|
+
// After
|
|
282
|
+
import { JwtVerifier } from '@notoofly/auth-server';
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
3. Update configuration:
|
|
286
|
+
```typescript
|
|
287
|
+
// Review configuration options for changes
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## 🤝 Contributing
|
|
291
|
+
|
|
292
|
+
1. Fork the repository
|
|
293
|
+
2. Create a feature branch
|
|
294
|
+
3. Make your changes
|
|
295
|
+
4. Add tests
|
|
296
|
+
5. Run `npm run test:ci`
|
|
297
|
+
6. Submit a pull request
|
|
298
|
+
|
|
299
|
+
## 📄 License
|
|
300
|
+
|
|
301
|
+
MIT License – see [LICENSE](LICENSE) file for details.
|
|
302
|
+
|
|
303
|
+
## 🆘 Support
|
|
304
|
+
|
|
305
|
+
- 📖 [Documentation](https://docs.notoofly.com)
|
|
306
|
+
- 🐛 [Issues](https://github.com/notoofly/auth-server/issues)
|
|
307
|
+
- 💬 [Discussions](https://github.com/notoofly/auth-server/discussions)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/elysia/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EACN,gBAAgB,EAChB,WAAW,EACX,qBAAqB,EACrB,eAAe,GACf,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/elysia/index.ts"],"names":[],"mappings":"AACA,OAAO,EACN,gBAAgB,EAChB,WAAW,EACX,qBAAqB,EACrB,eAAe,GACf,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { Elysia } from "elysia";
|
|
2
|
+
import type { AuthContext, GuardOptions, JwtVerificationConfig } from "../../types/index.js";
|
|
3
|
+
export interface ElysiaAuthOptions extends JwtVerificationConfig {
|
|
4
|
+
extractFrom?: "header" | "cookie" | "both";
|
|
5
|
+
cookieName?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface AuthContextElysia {
|
|
8
|
+
user: AuthContext["user"];
|
|
9
|
+
token: string;
|
|
10
|
+
}
|
|
11
|
+
export type AuthPluginContext = {
|
|
12
|
+
getAuth: () => Promise<AuthContextElysia | null>;
|
|
13
|
+
};
|
|
14
|
+
export declare function createAuthPlugin(options: ElysiaAuthOptions): Elysia<"", {
|
|
15
|
+
decorator: {};
|
|
16
|
+
store: {};
|
|
17
|
+
derive: {
|
|
18
|
+
readonly getAuth: () => Promise<AuthContextElysia | null>;
|
|
19
|
+
};
|
|
20
|
+
resolve: {};
|
|
21
|
+
}, {
|
|
22
|
+
typebox: {};
|
|
23
|
+
error: {};
|
|
24
|
+
}, {
|
|
25
|
+
schema: {};
|
|
26
|
+
standaloneSchema: {};
|
|
27
|
+
macro: {};
|
|
28
|
+
macroFn: {};
|
|
29
|
+
parser: {};
|
|
30
|
+
response: import("elysia").ExtractErrorFromHandle<{
|
|
31
|
+
readonly getAuth: () => Promise<AuthContextElysia | null>;
|
|
32
|
+
}>;
|
|
33
|
+
}, {}, {
|
|
34
|
+
derive: {};
|
|
35
|
+
resolve: {};
|
|
36
|
+
schema: {};
|
|
37
|
+
standaloneSchema: {};
|
|
38
|
+
response: {};
|
|
39
|
+
}, {
|
|
40
|
+
derive: {};
|
|
41
|
+
resolve: {};
|
|
42
|
+
schema: {};
|
|
43
|
+
standaloneSchema: {};
|
|
44
|
+
response: {};
|
|
45
|
+
}>;
|
|
46
|
+
export declare function createRoleGuard(role: string): Elysia<"", {
|
|
47
|
+
decorator: {};
|
|
48
|
+
store: {};
|
|
49
|
+
derive: {};
|
|
50
|
+
resolve: {};
|
|
51
|
+
}, {
|
|
52
|
+
typebox: {};
|
|
53
|
+
error: {};
|
|
54
|
+
}, {
|
|
55
|
+
schema: {};
|
|
56
|
+
standaloneSchema: {};
|
|
57
|
+
macro: {};
|
|
58
|
+
macroFn: {};
|
|
59
|
+
parser: {};
|
|
60
|
+
response: {};
|
|
61
|
+
}, {}, {
|
|
62
|
+
derive: {};
|
|
63
|
+
resolve: {};
|
|
64
|
+
schema: {};
|
|
65
|
+
standaloneSchema: {};
|
|
66
|
+
response: {};
|
|
67
|
+
}, {
|
|
68
|
+
derive: {};
|
|
69
|
+
resolve: {};
|
|
70
|
+
schema: {};
|
|
71
|
+
standaloneSchema: {};
|
|
72
|
+
response: {
|
|
73
|
+
200: {
|
|
74
|
+
success: boolean;
|
|
75
|
+
error: {
|
|
76
|
+
code: string;
|
|
77
|
+
message: string;
|
|
78
|
+
};
|
|
79
|
+
meta: {
|
|
80
|
+
timestamp: string;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
}>;
|
|
85
|
+
export declare function createPermissionGuard(permission: string): Elysia<"", {
|
|
86
|
+
decorator: {};
|
|
87
|
+
store: {};
|
|
88
|
+
derive: {};
|
|
89
|
+
resolve: {};
|
|
90
|
+
}, {
|
|
91
|
+
typebox: {};
|
|
92
|
+
error: {};
|
|
93
|
+
}, {
|
|
94
|
+
schema: {};
|
|
95
|
+
standaloneSchema: {};
|
|
96
|
+
macro: {};
|
|
97
|
+
macroFn: {};
|
|
98
|
+
parser: {};
|
|
99
|
+
response: {};
|
|
100
|
+
}, {}, {
|
|
101
|
+
derive: {};
|
|
102
|
+
resolve: {};
|
|
103
|
+
schema: {};
|
|
104
|
+
standaloneSchema: {};
|
|
105
|
+
response: {};
|
|
106
|
+
}, {
|
|
107
|
+
derive: {};
|
|
108
|
+
resolve: {};
|
|
109
|
+
schema: {};
|
|
110
|
+
standaloneSchema: {};
|
|
111
|
+
response: {
|
|
112
|
+
200: {
|
|
113
|
+
success: boolean;
|
|
114
|
+
error: {
|
|
115
|
+
code: string;
|
|
116
|
+
message: string;
|
|
117
|
+
};
|
|
118
|
+
meta: {
|
|
119
|
+
timestamp: string;
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
}>;
|
|
124
|
+
export declare function createGuard(options: GuardOptions): Elysia<"", {
|
|
125
|
+
decorator: {};
|
|
126
|
+
store: {};
|
|
127
|
+
derive: {};
|
|
128
|
+
resolve: {};
|
|
129
|
+
}, {
|
|
130
|
+
typebox: {};
|
|
131
|
+
error: {};
|
|
132
|
+
}, {
|
|
133
|
+
schema: {};
|
|
134
|
+
standaloneSchema: {};
|
|
135
|
+
macro: {};
|
|
136
|
+
macroFn: {};
|
|
137
|
+
parser: {};
|
|
138
|
+
response: {};
|
|
139
|
+
}, {}, {
|
|
140
|
+
derive: {};
|
|
141
|
+
resolve: {};
|
|
142
|
+
schema: {};
|
|
143
|
+
standaloneSchema: {};
|
|
144
|
+
response: {};
|
|
145
|
+
}, {
|
|
146
|
+
derive: {};
|
|
147
|
+
resolve: {};
|
|
148
|
+
schema: {};
|
|
149
|
+
standaloneSchema: {};
|
|
150
|
+
response: {
|
|
151
|
+
200: {
|
|
152
|
+
success: boolean;
|
|
153
|
+
error: {
|
|
154
|
+
code: string;
|
|
155
|
+
message: string;
|
|
156
|
+
};
|
|
157
|
+
meta: {
|
|
158
|
+
timestamp: string;
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
};
|
|
162
|
+
}>;
|
|
163
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../src/adapters/elysia/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,KAAK,EACX,WAAW,EACX,YAAY,EACZ,qBAAqB,EACrB,MAAM,sBAAsB,CAAC;AAO9B,MAAM,WAAW,iBAAkB,SAAQ,qBAAqB;IAC/D,WAAW,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC/B,OAAO,EAAE,MAAM,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;CACjD,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB;;;;gCAiCpC,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;;;;;;;;;;;;;gCAAjC,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;;;;;;;;;;;;;;GAiBvD;AAID,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsC3C;AAID,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCvD;AAID,wBAAgB,WAAW,CAAC,OAAO,EAAE,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoChD"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { Elysia } from "elysia";
|
|
2
|
+
import { JwtVerifier } from "../../core/jwt-verifier.js";
|
|
3
|
+
import { checkGuard } from "../../utils/authorization.js";
|
|
4
|
+
import { extractTokenFromCookie, extractTokenFromHeader, } from "../../utils/token-extraction.js";
|
|
5
|
+
export function createAuthPlugin(options) {
|
|
6
|
+
const verifier = new JwtVerifier(options);
|
|
7
|
+
const extractFrom = options.extractFrom ?? "header";
|
|
8
|
+
const cookieName = options.cookieName ?? "access_token";
|
|
9
|
+
return new Elysia({ name: "auth" }).derive({ as: "global" }, async ({ request }) => {
|
|
10
|
+
const authHeader = request.headers.get("authorization");
|
|
11
|
+
const cookieHeader = request.headers.get("cookie");
|
|
12
|
+
const extractToken = () => {
|
|
13
|
+
switch (extractFrom) {
|
|
14
|
+
case "header":
|
|
15
|
+
return extractTokenFromHeader(authHeader);
|
|
16
|
+
case "cookie":
|
|
17
|
+
return extractTokenFromCookie(cookieHeader, cookieName);
|
|
18
|
+
case "both":
|
|
19
|
+
return (extractTokenFromHeader(authHeader) ??
|
|
20
|
+
extractTokenFromCookie(cookieHeader, cookieName));
|
|
21
|
+
default:
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
const token = extractToken();
|
|
26
|
+
return {
|
|
27
|
+
getAuth: async () => {
|
|
28
|
+
if (!token)
|
|
29
|
+
return null;
|
|
30
|
+
try {
|
|
31
|
+
const user = await verifier.verifyAccessToken(token);
|
|
32
|
+
return {
|
|
33
|
+
user,
|
|
34
|
+
token,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
/* ---------------- ROLE GUARD ---------------- */
|
|
45
|
+
export function createRoleGuard(role) {
|
|
46
|
+
return new Elysia({ name: `role-guard-${role}` }).onBeforeHandle(async (ctx) => {
|
|
47
|
+
const { getAuth, set } = ctx;
|
|
48
|
+
const auth = await getAuth();
|
|
49
|
+
if (!auth) {
|
|
50
|
+
set.status = 401;
|
|
51
|
+
return {
|
|
52
|
+
success: false,
|
|
53
|
+
error: {
|
|
54
|
+
code: "AUTH.REQUIRED",
|
|
55
|
+
message: "Authentication required",
|
|
56
|
+
},
|
|
57
|
+
meta: {
|
|
58
|
+
timestamp: new Date().toISOString(),
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (!auth.user.roles?.includes(role)) {
|
|
63
|
+
set.status = 403;
|
|
64
|
+
return {
|
|
65
|
+
success: false,
|
|
66
|
+
error: {
|
|
67
|
+
code: "AUTH.ROLE.REQUIRED",
|
|
68
|
+
message: `Role '${role}' is required`,
|
|
69
|
+
},
|
|
70
|
+
meta: {
|
|
71
|
+
timestamp: new Date().toISOString(),
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
return;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/* ---------------- PERMISSION GUARD ---------------- */
|
|
79
|
+
export function createPermissionGuard(permission) {
|
|
80
|
+
return new Elysia({ name: `permission-guard-${permission}` }).onBeforeHandle(async (ctx) => {
|
|
81
|
+
const { getAuth, set } = ctx;
|
|
82
|
+
const auth = await getAuth();
|
|
83
|
+
if (!auth) {
|
|
84
|
+
set.status = 401;
|
|
85
|
+
return {
|
|
86
|
+
success: false,
|
|
87
|
+
error: {
|
|
88
|
+
code: "AUTH.REQUIRED",
|
|
89
|
+
message: "Authentication required",
|
|
90
|
+
},
|
|
91
|
+
meta: {
|
|
92
|
+
timestamp: new Date().toISOString(),
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
if (!auth.user.permissions?.includes(permission)) {
|
|
97
|
+
set.status = 403;
|
|
98
|
+
return {
|
|
99
|
+
success: false,
|
|
100
|
+
error: {
|
|
101
|
+
code: "AUTH.PERMISSION.REQUIRED",
|
|
102
|
+
message: `Permission '${permission}' is required`,
|
|
103
|
+
},
|
|
104
|
+
meta: {
|
|
105
|
+
timestamp: new Date().toISOString(),
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
return;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/* ---------------- CUSTOM GUARD ---------------- */
|
|
113
|
+
export function createGuard(options) {
|
|
114
|
+
return new Elysia({ name: "custom-guard" }).onBeforeHandle(async (ctx) => {
|
|
115
|
+
const { getAuth, set } = ctx;
|
|
116
|
+
const auth = await getAuth();
|
|
117
|
+
if (!auth) {
|
|
118
|
+
set.status = 401;
|
|
119
|
+
return {
|
|
120
|
+
success: false,
|
|
121
|
+
error: {
|
|
122
|
+
code: "AUTH.REQUIRED",
|
|
123
|
+
message: "Authentication required",
|
|
124
|
+
},
|
|
125
|
+
meta: {
|
|
126
|
+
timestamp: new Date().toISOString(),
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
if (!checkGuard(auth.user, options)) {
|
|
131
|
+
set.status = 403;
|
|
132
|
+
return {
|
|
133
|
+
success: false,
|
|
134
|
+
error: {
|
|
135
|
+
code: "AUTH.GUARD.FAILED",
|
|
136
|
+
message: "Access denied by authorization guard",
|
|
137
|
+
},
|
|
138
|
+
meta: {
|
|
139
|
+
timestamp: new Date().toISOString(),
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
return;
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../../src/adapters/elysia/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAMzD,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EACN,sBAAsB,EACtB,sBAAsB,GACtB,MAAM,iCAAiC,CAAC;AAgBzC,MAAM,UAAU,gBAAgB,CAAC,OAA0B;IAC1D,MAAM,QAAQ,GAAG,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,QAAQ,CAAC;IACpD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,cAAc,CAAC;IAExD,OAAO,IAAI,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,CACzC,EAAE,EAAE,EAAE,QAAQ,EAAE,EAChB,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;QACrB,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QACxD,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAEnD,MAAM,YAAY,GAAG,GAAkB,EAAE;YACxC,QAAQ,WAAW,EAAE,CAAC;gBACrB,KAAK,QAAQ;oBACZ,OAAO,sBAAsB,CAAC,UAAU,CAAC,CAAC;gBAE3C,KAAK,QAAQ;oBACZ,OAAO,sBAAsB,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;gBAEzD,KAAK,MAAM;oBACV,OAAO,CACN,sBAAsB,CAAC,UAAU,CAAC;wBAClC,sBAAsB,CAAC,YAAY,EAAE,UAAU,CAAC,CAChD,CAAC;gBAEH;oBACC,OAAO,IAAI,CAAC;YACd,CAAC;QACF,CAAC,CAAC;QAEF,MAAM,KAAK,GAAG,YAAY,EAAE,CAAC;QAE7B,OAAO;YACN,OAAO,EAAE,KAAK,IAAuC,EAAE;gBACtD,IAAI,CAAC,KAAK;oBAAE,OAAO,IAAI,CAAC;gBAExB,IAAI,CAAC;oBACJ,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;oBAErD,OAAO;wBACN,IAAI;wBACJ,KAAK;qBACL,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACR,OAAO,IAAI,CAAC;gBACb,CAAC;YACF,CAAC;SACD,CAAC;IACH,CAAC,CACD,CAAC;AACH,CAAC;AAED,kDAAkD;AAElD,MAAM,UAAU,eAAe,CAAC,IAAY;IAC3C,OAAO,IAAI,MAAM,CAAC,EAAE,IAAI,EAAE,cAAc,IAAI,EAAE,EAAE,CAAC,CAAC,cAAc,CAC/D,KAAK,EAAE,GAAG,EAAE,EAAE;QACb,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAqC,CAAC;QAE/D,MAAM,IAAI,GAAG,MAAM,OAAO,EAAE,CAAC;QAE7B,IAAI,CAAC,IAAI,EAAE,CAAC;YACX,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,OAAO;gBACN,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE;oBACN,IAAI,EAAE,eAAe;oBACrB,OAAO,EAAE,yBAAyB;iBAClC;gBACD,IAAI,EAAE;oBACL,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBACnC;aACD,CAAC;QACH,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACtC,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,OAAO;gBACN,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE;oBACN,IAAI,EAAE,oBAAoB;oBAC1B,OAAO,EAAE,SAAS,IAAI,eAAe;iBACrC;gBACD,IAAI,EAAE;oBACL,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBACnC;aACD,CAAC;QACH,CAAC;QAED,OAAO;IACR,CAAC,CACD,CAAC;AACH,CAAC;AAED,wDAAwD;AAExD,MAAM,UAAU,qBAAqB,CAAC,UAAkB;IACvD,OAAO,IAAI,MAAM,CAAC,EAAE,IAAI,EAAE,oBAAoB,UAAU,EAAE,EAAE,CAAC,CAAC,cAAc,CAC3E,KAAK,EAAE,GAAG,EAAE,EAAE;QACb,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAqC,CAAC;QAE/D,MAAM,IAAI,GAAG,MAAM,OAAO,EAAE,CAAC;QAE7B,IAAI,CAAC,IAAI,EAAE,CAAC;YACX,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,OAAO;gBACN,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE;oBACN,IAAI,EAAE,eAAe;oBACrB,OAAO,EAAE,yBAAyB;iBAClC;gBACD,IAAI,EAAE;oBACL,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBACnC;aACD,CAAC;QACH,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAClD,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,OAAO;gBACN,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE;oBACN,IAAI,EAAE,0BAA0B;oBAChC,OAAO,EAAE,eAAe,UAAU,eAAe;iBACjD;gBACD,IAAI,EAAE;oBACL,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBACnC;aACD,CAAC;QACH,CAAC;QAED,OAAO;IACR,CAAC,CACD,CAAC;AACH,CAAC;AAED,oDAAoD;AAEpD,MAAM,UAAU,WAAW,CAAC,OAAqB;IAChD,OAAO,IAAI,MAAM,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC,cAAc,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QACxE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAqC,CAAC;QAE/D,MAAM,IAAI,GAAG,MAAM,OAAO,EAAE,CAAC;QAE7B,IAAI,CAAC,IAAI,EAAE,CAAC;YACX,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,OAAO;gBACN,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE;oBACN,IAAI,EAAE,eAAe;oBACrB,OAAO,EAAE,yBAAyB;iBAClC;gBACD,IAAI,EAAE;oBACL,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBACnC;aACD,CAAC;QACH,CAAC;QAED,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC;YACrC,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,OAAO;gBACN,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE;oBACN,IAAI,EAAE,mBAAmB;oBACzB,OAAO,EAAE,sCAAsC;iBAC/C;gBACD,IAAI,EAAE;oBACL,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBACnC;aACD,CAAC;QACH,CAAC;QAED,OAAO;IACR,CAAC,CAAC,CAAC;AACJ,CAAC"}
|