| π΄ Forks | ||||
Provide a secure, selfβhostable weather backend that developers and teams can trust.
- OAuth 2.0 first β secure by design.
- Pluggable data sources and token stores (Redis / memory).
- Low-latency with caching and sensible defaults for production.
Why choose this project:
- Security: full OAuth flows, introspection, revocation.
- Control: selfβhost to avoid vendor limits and protect data.
- Extensible: add scrapers or adapters without touching auth.
- Production-ready: caching, rate limiting, and audit logging.
This project implements a complete OAuth 2.0 system following RFC 6749, RFC 7662 (Token Introspection), and RFC 7009 (Token Revocation).
RFC 7662 compliant token introspection endpoint that validates tokens and returns detailed information.
Request:
curl -X POST http://localhost:5000/oauth/introspect \
-H "Authorization: Basic $(echo -n 'client-id:client-secret' | base64)" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "token=your-access-token"Response for Valid Token:
{
"active": true,
"scope": "read write",
"client_id": "weather-api-client",
"username": "[email protected]",
"token_type": "access_token",
"exp": 1700000000,
"iat": 1699990000,
"sub": "user-123",
"aud": "weather-api",
"iss": "weather-api-oauth",
"jti": "token-uuid",
"nbf": 1699990000,
"user_id": "user-123",
"token_use": "access",
"auth_time": 1699990000,
"permissions": ["read", "write"],
"client_name": "Weather API Client",
"issued_for": "weather-api"
}Response for Invalid/Expired Token:
{
"active": false
}Refresh expired access tokens using refresh tokens.
Request:
curl -X POST http://localhost:5000/oauth/token \
-H "Authorization: Basic $(echo -n 'client-id:client-secret' | base64)" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token&refresh_token=your-refresh-token"Response:
{
"access_token": "new-access-token",
"refresh_token": "new-refresh-token",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "read write"
}Get access tokens for service-to-service communication.
Request:
curl -X POST http://localhost:5000/oauth/token \
-H "Authorization: Basic $(echo -n 'client-id:client-secret' | base64)" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials&scope=read"Revoke access or refresh tokens.
Request:
curl -X POST http://localhost:5000/oauth/revoke \
-H "Authorization: Basic $(echo -n 'client-id:client-secret' | base64)" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "token=token-to-revoke"Issue demo tokens for testing purposes.
Request:
curl -X POST http://localhost:5000/oauth/demo/issue \
-H "Authorization: Basic $(echo -n 'client-id:client-secret' | base64)" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "[email protected]&scope=read write"curl -H "Authorization: Basic $(echo -n 'client-id:client-secret' | base64)" \
http://localhost:5000/oauth/introspectcurl -H "Authorization: Bearer your-client-secret" \
-d "client_id=your-client-id" \
http://localhost:5000/oauth/introspectcurl -d "client_id=your-client-id&client_secret=your-client-secret" \
http://localhost:5000/oauth/introspectAll weather API endpoints are protected by OAuth middleware. Include your access token in the Authorization header:
curl -H "Authorization: Bearer your-access-token" \
http://localhost:5000/api/weather/londonconst { requireAuth } = require("./src/middlewares/oauth.middleware");
// Require any valid token
app.get("/protected", requireAuth(), (req, res) => {
res.json({ user: req.user });
});
// Require specific scopes
app.get("/admin", requireAuth(["write"]), (req, res) => {
res.json({ user: req.user });
});const { optionalAuth } = require("./src/middlewares/oauth.middleware");
app.get("/public", optionalAuth, (req, res) => {
if (req.user) {
res.json({ authenticated: true, user: req.user });
} else {
res.json({ authenticated: false });
}
});const { requireValidToken } = require("./src/middlewares/oauth.middleware");
// Uses token introspection for comprehensive validation
app.get("/secure", requireValidToken(["read", "write"]), (req, res) => {
res.json({ user: req.user });
});Set these environment variables for OAuth configuration:
# JWT Configuration
JWT_SECRET=your-super-secret-jwt-key
JWT_ACCESS_TOKEN_EXPIRY=3600
JWT_REFRESH_TOKEN_EXPIRY=604800
# OAuth Client Configuration
OAUTH_CLIENT_ID=your-client-id
OAUTH_CLIENT_SECRET=your-client-secret
# Token Storage
TOKEN_STORAGE=redis # or 'memory'
REDIS_URL=redis://localhost:6379
REDIS_PASSWORD=your-redis-password
# Security
NODE_ENV=production # Enables HTTPS requirement- Token Rotation: Refresh tokens are rotated on each use
- Rate Limiting: Built-in rate limiting for all OAuth endpoints
- HTTPS Enforcement: HTTPS required in production
- Token Revocation: Immediate token invalidation
- Scope Validation: Granular permission checking
- Client Authentication: Multiple authentication methods supported
- Token Caching: Redis-based caching for performance
- Audit Logging: Comprehensive request logging
Weather-API/
βββ π .github/ #GitHub configuration
β βββ π ISSUE_TEMPLATE/ # Issue templates
β β βββ bug_report.md
β β βββ documentation.md
β β βββ feature_request.md
β β βββ performance.md
β βββ π workflows/ # GitHub Actions workflows
β β βββ bundlewatch.yml
β β βββ dependabot.yml
β β βββ lint.yml
β β βββ performance.yml
β β βββ render-build.yml
β β βββ security.yml
β β βββ test.yml
β β βββ uptime.yml
β βββ dependabot.yml
β βββ PULL_REQUEST_TEMPLATE.md
βββ π docs/ # Documentation
β βββ MONITORING.md
β βββ MOST_IMPORTANT_FOR_DEVELOPERS.md
β βββ OAUTH.md
β βββ REDIS_CACHE.md
βββ π public/ # Frontend assets
β βββ π admin/ # Admin panel
β β βββ cache.html
β β βββ dashboard.html
β β βββ login.html
β βββ π assets/ # Static assets
β β βββ gssoc_logo.png
β β βββ WeatherBackground.jpg
β βββ π css/ # Stylesheets
β β βββ cache.css
β β βββ dashboard.css
β β βββ login.css
β βββ π Favicon/ # Favicon files
β β βββ Favicon.PNG
β βββ π js/ # JavaScript files
β β βββ cache.js
β β βββ dashboard.js
β β βββ login.js
β βββ fallback.png
β βββ index.html
β βββ script.js
β βββ style.css
β βββ sw.js
β βββ theme-manager.js
β βββ themes.css
βββ π scripts/ # Utility scripts
β βββ test-oauth.js
β βββ test-redis.js
βββ π src/ # Source code
β βββ π config/ # Configuration files
β β βββ cors.js
β β βββ database.js
β β βββ env.js
β β βββ monitoring.config.js
β β βββ oauth.js
β βββ π constants/ # Application constants
β β βββ selectors.js
β βββ π controllers/ # Route controllers
β β βββ oauth.controller.js
β β βββ weather.controller.js
β βββ π database/ # Database configuration
β β βββ π migrations/ # Database migrations
β β β βββ 001_initial_schema.js
β β β βββ 002_add_oauth_tables.js
β β βββ init.js
β βββ π middlewares/ # Express middlewares
β β βββ cache.middleware.js
β β βββ error.middleware.js
β β βββ headers.middleware.js
β β βββ logging.middleware.js
β β βββ oauth.middleware.js
β β βββ rateLimiter.middleware.js
β βββ π routes/ # API routes
β β βββ admin.routes.js
β β βββ configRoutes.js
β β βββ oauth.routes.js
β β βββ weather.routes.js
β βββ π services/ # Business logic
β β βββ cache.service.js
β β βββ cacheWarming.service.js
β β βββ email.service.js
β β βββ monitoring.service.js
β β βββ oauth.service.js
β β βββ redis.service.js
β β βββ selectorValidation.service.js
β β βββ tokenStorage.service.js
β β βββ user.service.js
β β βββ weather.service.js
β βββ π utils/ # Utility functions
β βββ ip.js
β βββ logger.js
β βββ parser.js
β βββ sanitize.js
βββ π test/ # Test files
β βββ monitoring.test.js
β βββ oauth.test.js
β βββ server.test.js
β βββ weather.test.js
βββ .env.example # Environment variables template
βββ .gitignore # Git ignore rules
βββ .lighthouserc.js # Lighthouse configuration
βββ babel.config.js # Babel configuration
βββ Code of Conduct.md # Community guidelines
βββ Contributing.md # Contribution guidelines
βββ docker-compose.yaml # Docker compose configuration
βββ Dockerfile # Docker configuration
βββ eslint.config.js # ESLint configuration
βββ jest.config.js # Jest configuration
βββ jest.setup.js # Jest setup file
βββ LICENSE.md # License information
βββ MONITORING.md # Monitoring documentation
βββ package-lock.json # NPM lock file
βββ package.json # NPM package configuration
βββ README.md # Project documentation
βββ Security.md # Security policy
βββ server.js # Main server file
βββ THEME_IMPLEMENTATION.md # Theme implementation guide\
Have ideas, feedback, or just want to say hi?
- π οΈ Open an issue in the repository
To ensure a welcoming and inclusive environment, we have a Code of Conduct that all contributors are expected to follow. In short: Be respectful, be kind, and be collaborative. Please read the full Code of Conduct before participating.
This project is licensed under the MIT License.
Feel free to open issues or discussions if you have any feedback, feature suggestions, or want to collaborate!
| Error Code | HTTP Status | Description |
|---|---|---|
invalid_request |
400 | Missing required parameters |
invalid_client |
401 | Invalid client credentials |
invalid_grant |
400 | Invalid refresh token |
invalid_token |
401 | Invalid or expired token |
insufficient_scope |
403 | Token lacks required scopes |
unsupported_grant_type |
400 | Unsupported grant type |
server_error |
500 | Internal server error |
- Missing env vars β add .env or set required keys (JWT_SECRET, OAUTH_CLIENT_ID/SECRET).
- Server wonβt start β check PORT, kill conflicting process, or change port.
- Redis errors β verify REDIS_URL/credentials or set TOKEN_STORAGE=memory for dev.
- Introspection shows inactive β confirm token, client auth method, and clock sync.
- Refresh token failing β ensure you use the latest rotated refresh token.
- CORS or frontend blocks β update allowed origins in src/config/cors.js.
- Tests failing β run with TOKEN_STORAGE=memory, npm install, then npm test.
Run the comprehensive test suite:
npm testThe test suite covers:
- Token introspection for valid, expired, and invalid tokens
- Refresh token flow
- Client credentials flow
- Token revocation
- Middleware behavior
- Security edge cases
- Rate limiting
- Caching: Introspection results are cached for 5 minutes
- Redis: Optional Redis backend for high-performance token storage
- Memory Fallback: Automatic fallback to memory storage if Redis unavailable
- Rate Limiting: Configurable rate limits to prevent abuse
- Set
NODE_ENV=productionto enable HTTPS enforcement - Use strong JWT secrets (256+ bits)
- Configure Redis for token storage
- Set up proper CORS configuration
- Monitor rate limiting and token usage
- Regular security audits and token cleanup
GET /api/weather/:city- Get current weather for a cityGET /api/weather-forecast/:city- Get weather forecast for a city
GET /config- Get API configurationGET /api/version- Get API version
All endpoints require OAuth authentication with appropriate scopes.
- Fork β branch (e.g., feat/β¦, fix/β¦, docs/β¦).
- Code + tests + docs: run npm install, npm test, and lint before committing.
- Commit style: Conventional Commits (feat:, fix:, docs:, test:).
- Open a focused PR with: description, testing steps, and checklist: tests, docs, lint.
- Never commit secrets; use .env.example for config samples.
Please read CONTRIBUTING.md for details on our code of conduct and the process for submitting pull requests.
This project is licensed under the ISC License - see the LICENSE.md file for details.
|
Gaurav Karakoti
|
We love our contributors! If you'd like to help, please check out our CONTRIBUTE.md file for guidelines.
π Stay Ahead of the Weather β One City at a Time! πβοΈπ§οΈ
π¨βπ» Developed By β€οΈGauravKarakotiβ€οΈ GitHub | LinkedIn

