{"id":27400181,"url":"https://github.com/dokadev/jwt-auth-svc","last_synced_at":"2025-09-04T05:46:27.067Z","repository":{"id":281305923,"uuid":"944885039","full_name":"DokaDev/jwt-auth-svc","owner":"DokaDev","description":null,"archived":false,"fork":false,"pushed_at":"2025-03-08T06:46:15.000Z","size":0,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-08T07:28:45.206Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DokaDev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-08T06:46:00.000Z","updated_at":"2025-03-08T06:46:20.000Z","dependencies_parsed_at":"2025-03-08T07:38:49.693Z","dependency_job_id":null,"html_url":"https://github.com/DokaDev/jwt-auth-svc","commit_stats":null,"previous_names":["dokadev/jwt-auth-svc"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DokaDev%2Fjwt-auth-svc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DokaDev%2Fjwt-auth-svc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DokaDev%2Fjwt-auth-svc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DokaDev%2Fjwt-auth-svc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DokaDev","download_url":"https://codeload.github.com/DokaDev/jwt-auth-svc/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248814925,"owners_count":21165852,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-04-14T03:26:38.555Z","updated_at":"2025-04-14T03:26:39.168Z","avatar_url":"https://github.com/DokaDev.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Spring Boot JWT Authentication Service\n\nThis backend service implements a complete JWT (JSON Web Token) authentication system using Spring Boot, providing secure API endpoints for user authentication and authorization.\n\n## Architecture Overview\n\n```mermaid\ngraph TD\n    subgraph \"Controllers Layer\"\n        AC[AuthController]\n        ATC[ApiTestController]\n        TC[TestController]\n    end\n    \n    subgraph \"Service Layer\"\n        AS[AuthService]\n        JS[JwtService]\n    end\n    \n    subgraph \"Data Storage\"\n        RD[Redis]\n    end\n    \n    AC --\u003e AS\n    ATC --\u003e JS\n    AS --\u003e JS\n    JS --\u003e RD\n```\n\n## Project Structure\n\n```\nsrc/main/java/com/dokalab/auth/\n├── config/\n│   ├── CorsConfig.java        # CORS configuration\n│   ├── RedisConfig.java       # Redis connection configuration\n│   └── SecurityConfig.java    # Security settings\n├── controller/\n│   ├── ApiTestController.java # Protected API endpoints\n│   ├── AuthController.java    # Authentication endpoints\n│   └── TestController.java    # Basic server test endpoint\n├── model/\n│   ├── AuthResponse.java      # Authentication response model\n│   ├── AuthTokens.java        # Token pair model\n│   ├── JwtConstants.java      # JWT configuration constants\n│   ├── JwtPayload.java        # JWT payload structure\n│   ├── LoginCredentials.java  # Login request model\n│   └── User.java              # User information model\n├── service/\n│   ├── AuthService.java       # Authentication service\n│   └── JwtService.java        # JWT token operations\n└── AuthServiceTestApplication.java # Main application\n```\n\n## Authentication Flow\n\n### Login Process\n\n```mermaid\nsequenceDiagram\n    participant Client\n    participant AuthController\n    participant AuthService\n    participant JwtService\n    participant Redis\n    \n    Client-\u003e\u003eAuthController: POST /api/auth/login\n    AuthController-\u003e\u003eAuthService: login(credentials)\n    AuthService-\u003e\u003eAuthService: Validate credentials\n    AuthService-\u003e\u003eJwtService: generateTokens(user)\n    JwtService-\u003e\u003eJwtService: generateAccessToken(user)\n    JwtService-\u003e\u003eJwtService: generateRefreshToken(user)\n    JwtService-\u003e\u003eRedis: Store refresh token\n    JwtService--\u003e\u003eAuthService: Return token pair\n    AuthService--\u003e\u003eAuthController: Return AuthResponse\n    AuthController--\u003e\u003eClient: Return tokens and user info\n```\n\n### Token Refresh Process\n\n```mermaid\nsequenceDiagram\n    participant Client\n    participant AuthController\n    participant AuthService\n    participant JwtService\n    participant Redis\n    \n    Client-\u003e\u003eAuthController: POST /api/auth/refresh\n    AuthController-\u003e\u003eAuthService: refreshToken(refreshToken)\n    AuthService-\u003e\u003eJwtService: extractRefreshTokenPayload(token)\n    JwtService--\u003e\u003eAuthService: Return payload\n    AuthService-\u003e\u003eJwtService: validateRefreshToken(token, userId)\n    JwtService-\u003e\u003eRedis: Check stored refresh token\n    JwtService--\u003e\u003eAuthService: Return validation result\n    AuthService-\u003e\u003eJwtService: generateTokens(user)\n    JwtService-\u003e\u003eRedis: Update refresh token\n    JwtService--\u003e\u003eAuthService: Return new tokens\n    AuthService--\u003e\u003eAuthController: Return new token pair\n    AuthController--\u003e\u003eClient: Return new tokens\n```\n\n### Logout Process\n\n```mermaid\nsequenceDiagram\n    participant Client\n    participant AuthController\n    participant AuthService\n    participant JwtService\n    participant Redis\n    \n    Client-\u003e\u003eAuthController: POST /api/auth/logout\n    AuthController-\u003e\u003eAuthService: logout(accessToken, userId)\n    AuthService-\u003e\u003eJwtService: blacklistToken(accessToken)\n    JwtService-\u003e\u003eRedis: Add to blacklist\n    AuthService-\u003e\u003eJwtService: deleteRefreshToken(userId)\n    JwtService-\u003e\u003eRedis: Delete refresh token\n    AuthService--\u003e\u003eAuthController: Return success\n    AuthController--\u003e\u003eClient: Return success response\n```\n\n## JWT Token Details\n\n### Access Token Structure\n\n```mermaid\ngraph TD\n    subgraph \"JWT Access Token\"\n        H[Header] --- P[Payload] --- S[Signature]\n    end\n    \n    subgraph \"Header\"\n        H1[\"alg: HS256\"]\n        H2[\"typ: JWT\"]\n    end\n    \n    subgraph \"Payload\"\n        P1[\"sub: userId\"]\n        P2[\"email: user@example.com\"]\n        P3[\"name: User Name\"]\n        P4[\"role: user/admin\"]\n        P5[\"iat: issuedAt timestamp\"]\n        P6[\"exp: expiration timestamp\"]\n    end\n    \n    subgraph \"Signature\"\n        S1[\"HMAC-SHA256(base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret)\"]\n    end\n    \n    H --- H1 \u0026 H2\n    P --- P1 \u0026 P2 \u0026 P3 \u0026 P4 \u0026 P5 \u0026 P6\n    S --- S1\n```\n\n### Refresh Token Structure\n\n```mermaid\ngraph TD\n    subgraph \"JWT Refresh Token\"\n        H[Header] --- P[Payload] --- S[Signature]\n    end\n    \n    subgraph \"Header\"\n        H1[\"alg: HS256\"]\n        H2[\"typ: JWT\"]\n    end\n    \n    subgraph \"Payload\"\n        P1[\"sub: userId\"]\n        P2[\"iat: issuedAt timestamp\"]\n        P3[\"exp: expiration timestamp\"]\n    end\n    \n    subgraph \"Signature\"\n        S1[\"HMAC-SHA256(base64UrlEncode(header) + '.' + base64UrlEncode(payload), refreshSecret)\"]\n    end\n    \n    H --- H1 \u0026 H2\n    P --- P1 \u0026 P2 \u0026 P3\n    S --- S1\n```\n\n## API Endpoints\n\n### Authentication Endpoints\n\n| Endpoint | Method | Description | Request Body | Response |\n|----------|--------|-------------|--------------|----------|\n| `/api/auth/login` | POST | Authenticate user and issue tokens | `{ \"email\": \"...\", \"password\": \"...\" }` | `{ \"user\": {...}, \"tokens\": {...} }` |\n| `/api/auth/refresh` | POST | Refresh tokens | `{ \"refreshToken\": \"...\" }` | `{ \"accessToken\": \"...\", \"refreshToken\": \"...\" }` |\n| `/api/auth/verify` | POST | Verify token validity | `{ \"token\": \"...\" }` | `{ \"valid\": true/false }` |\n| `/api/auth/logout` | POST | Logout user | `{ \"accessToken\": \"...\", \"userId\": \"...\" }` | `{ \"success\": true }` |\n| `/api/auth/me` | POST | Get user info from token | `{ \"token\": \"...\" }` | User object |\n\n### Test Endpoints\n\n| Endpoint | Method | Auth Required | Description |\n|----------|--------|---------------|-------------|\n| `/test` | GET | No | Basic server health check |\n| `/api/public` | GET | No | Public test endpoint |\n| `/api/protected` | GET | Yes | Protected test endpoint |\n| `/api/admin` | GET | Yes (admin role) | Admin-only test endpoint |\n\n## Security Features\n\n1. **JWT-based Authentication**: Stateless authentication using signed JWT tokens\n2. **Token Refresh Mechanism**: Short-lived access tokens with refresh capability\n3. **Token Blacklisting**: Revocation of tokens on logout\n4. **Role-based Authorization**: Different access levels based on user roles\n5. **Redis Token Storage**: External persistence for refresh tokens and blacklist\n6. **CORS Protection**: Configured to allow specific origins only\n7. **Secure Signing Keys**: Separate keys for access and refresh tokens\n\n## Configuration\n\n### JWT Settings\n\nJWT settings are defined in `JwtConstants.java`:\n\n```java\npublic class JwtConstants {\n    // JWT secret keys (should be managed with environment variables in production)\n    public static final String JWT_SECRET = \"a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6\";\n    public static final String JWT_REFRESH_SECRET = \"z6y5x4w3v2u1t0s9r8q7p6o5n4m3l2k1j0i9h8g7f6e5d4c3b2a1\";\n    \n    // Token expiration times (in seconds)\n    public static final int ACCESS_TOKEN_EXPIRY = 15;  // 15 seconds (short time for testing)\n    public static final int REFRESH_TOKEN_EXPIRY = 600; // 10 minutes\n    \n    // Token type\n    public static final String TOKEN_TYPE = \"Bearer\";\n}\n```\n\n\u003e **Important:** For production, secrets should be stored in environment variables or a secure vault.\n\n### Redis Configuration\n\nRedis connection settings are configured in `RedisConfig.java`:\n\n```java\n@Bean\npublic RedisConnectionFactory redisConnectionFactory() {\n    RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration();\n    redisConfig.setHostName(\"127.0.0.1\");\n    redisConfig.setPort(6379);\n    redisConfig.setPassword(\"userpw\");\n    return new LettuceConnectionFactory(redisConfig);\n}\n```\n\n### CORS Configuration\n\nCORS is configured in `CorsConfig.java` to allow requests from specific origins:\n\n```java\n// Allow specific origins (client URLs)\nconfig.setAllowedOrigins(Arrays.asList(\"http://localhost:3000\", \"http://localhost:3001\"));\n// Allow all headers\nconfig.addAllowedHeader(\"*\");\n// Allow all HTTP methods\nconfig.addAllowedMethod(\"*\");\n// Allow credentials (cookies)\nconfig.setAllowCredentials(true);\n```\n\n## How to Run\n\n### Prerequisites\n\n- Java 17 or higher\n- Maven or Gradle\n- Redis server\n\n### Starting the Service\n\n1. Start Redis server (or use Docker):\n   ```bash\n   docker run --name redis -p 6379:6379 -d redis\n   ```\n\n2. Run the application:\n   ```bash\n   ./mvnw spring-boot:run\n   ```\n\n3. The server will start on port 8080.\n\n## Testing\n\nYou can use the provided `test-token-refresh.sh` script in the root project folder to test the authentication flow:\n\n```bash\n./test-token-refresh.sh\n```\n\nThis script:\n1. Attempts to login with test credentials\n2. Tests protected API access\n3. Waits for token expiration\n4. Tests token refresh\n5. Verifies access with the new token\n\n## Security Considerations for Production\n\nFor a production environment, consider the following:\n\n1. **Environment Variables**: Move all secrets to environment variables\n2. **HTTPS**: Always use HTTPS in production\n3. **Token Expiration**: Adjust token expiration times based on security requirements\n4. **Strong Keys**: Use a secure random key generator for JWT secrets\n5. **Rate Limiting**: Implement rate limiting on login and token refresh endpoints\n6. **Monitoring**: Add logging for security events and configure alerts\n7. **Regular Rotation**: Implement a mechanism for regular refresh token rotation ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdokadev%2Fjwt-auth-svc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdokadev%2Fjwt-auth-svc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdokadev%2Fjwt-auth-svc/lists"}