Skip to content

Commit b1a2087

Browse files
committed
feat(api): Enable CORS and auth middleware
- Added CORS configuration - Configurable allowed origin - Enabled credentials - Added auth middleware
1 parent 288e1ff commit b1a2087

File tree

1 file changed

+61
-15
lines changed

1 file changed

+61
-15
lines changed

routes/api/v1/_middleware.dart

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,67 @@
1+
import 'dart:io' show Platform; // To read environment variables
2+
13
import 'package:dart_frog/dart_frog.dart';
24
import 'package:ht_api/src/middlewares/authentication_middleware.dart';
5+
import 'package:shelf_cors_headers/shelf_cors_headers.dart' as shelf_cors;
36

47
Handler middleware(Handler handler) {
5-
// This middleware applies the `authenticationProvider` to all routes
8+
// This middleware applies providers and CORS handling to all routes
69
// under /api/v1/.
7-
//
8-
// The `authenticationProvider()` (from `lib/src/middlewares/authentication_middleware.dart`):
9-
// 1. Attempts to extract a Bearer token from the 'Authorization' header.
10-
// 2. Validates the token using the `AuthTokenService` (which must be
11-
// provided by an ancestor middleware, e.g., `routes/_middleware.dart`).
12-
// 3. Provides the resulting `User?` (nullable User object) into the request
13-
// context. This makes `context.read<User?>()` available downstream.
14-
//
15-
// IMPORTANT: `authenticationProvider()` itself does NOT block unauthenticated
16-
// requests. It simply makes the user's identity available if authentication
17-
// is successful. Stricter access control (blocking unauthenticated users)
18-
// is handled by `requireAuthentication()` middleware applied in more specific
19-
// route groups (e.g., `/api/v1/data/_middleware.dart`).
20-
return handler.use(authenticationProvider());
10+
11+
// --- CORS Configuration ---
12+
final allowedOriginEnv = Platform.environment['CORS_ALLOWED_ORIGIN'];
13+
String effectiveOrigin;
14+
15+
if (allowedOriginEnv != null && allowedOriginEnv.isNotEmpty) {
16+
effectiveOrigin = allowedOriginEnv;
17+
print(
18+
'[CORS Middleware] Using Access-Control-Allow-Origin from '
19+
'CORS_ALLOWED_ORIGIN environment variable: "$effectiveOrigin"',
20+
);
21+
} else {
22+
// IMPORTANT: Default for local development ONLY if env var is not set.
23+
// You MUST set CORS_ALLOWED_ORIGIN in production for security.
24+
// This default allows credentials, so it cannot be '*'.
25+
// Adjust 'http://localhost:3000' if your local Flutter web dev server
26+
// typically runs on a different port.
27+
effectiveOrigin = 'http://localhost:3000';
28+
print('------------------------------------------------------------------');
29+
print('WARNING: CORS_ALLOWED_ORIGIN environment variable is NOT SET.');
30+
print(
31+
'Defaulting Access-Control-Allow-Origin to: "$effectiveOrigin" '
32+
'FOR DEVELOPMENT ONLY.',
33+
);
34+
print(
35+
'For production, you MUST set the CORS_ALLOWED_ORIGIN environment '
36+
"variable to your Flutter web application's specific domain.",
37+
);
38+
print('------------------------------------------------------------------');
39+
}
40+
41+
final corsConfig = <String, String>{
42+
// Use the determined origin (from env var or development default)
43+
shelf_cors.ACCESS_CONTROL_ALLOW_ORIGIN: effectiveOrigin,
44+
// Crucial for authenticated APIs where the frontend sends credentials
45+
// (e.g., Authorization header with fetch({ credentials: 'include' }))
46+
shelf_cors.ACCESS_CONTROL_ALLOW_CREDENTIALS: 'true',
47+
// Define allowed HTTP methods
48+
shelf_cors.ACCESS_CONTROL_ALLOW_METHODS: 'GET, POST, PUT, DELETE, OPTIONS',
49+
// Define allowed headers from the client
50+
shelf_cors.ACCESS_CONTROL_ALLOW_HEADERS:
51+
'Origin, Content-Type, Authorization, Accept',
52+
// Optional: How long the results of a preflight request can be cached
53+
shelf_cors.ACCESS_CONTROL_MAX_AGE: '86400', // 24 hours
54+
};
55+
56+
// Apply CORS middleware first.
57+
// `fromShelfMiddleware` adapts the Shelf-based CORS middleware for Dart Frog.
58+
var newHandler = handler.use(
59+
fromShelfMiddleware(shelf_cors.corsHeaders(headers: corsConfig)),
60+
);
61+
62+
// Then apply the authenticationProvider.
63+
// ignore: join_return_with_assignment
64+
newHandler = newHandler.use(authenticationProvider());
65+
66+
return newHandler;
2167
}

0 commit comments

Comments
 (0)