{"id":50459997,"url":"https://github.com/aayushxrj/todo-springboot-flutter","last_synced_at":"2026-06-01T04:04:14.272Z","repository":{"id":357122117,"uuid":"1231591890","full_name":"aayushxrj/todo-springboot-flutter","owner":"aayushxrj","description":"To-Do-List made using Flutter and Springboot","archived":false,"fork":false,"pushed_at":"2026-05-23T05:18:35.000Z","size":361,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-23T06:34:14.515Z","etag":null,"topics":["flutter-web","grafana","kubernetes","permify","prometheus","spring-boot","todo-list"],"latest_commit_sha":null,"homepage":"","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/aayushxrj.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-07T05:25:55.000Z","updated_at":"2026-05-23T05:18:38.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/aayushxrj/todo-springboot-flutter","commit_stats":null,"previous_names":["aayushxrj/todo-springboot-flutter"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/aayushxrj/todo-springboot-flutter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aayushxrj%2Ftodo-springboot-flutter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aayushxrj%2Ftodo-springboot-flutter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aayushxrj%2Ftodo-springboot-flutter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aayushxrj%2Ftodo-springboot-flutter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aayushxrj","download_url":"https://codeload.github.com/aayushxrj/todo-springboot-flutter/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aayushxrj%2Ftodo-springboot-flutter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33759205,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-01T02:00:06.963Z","response_time":115,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["flutter-web","grafana","kubernetes","permify","prometheus","spring-boot","todo-list"],"created_at":"2026-06-01T04:04:12.288Z","updated_at":"2026-06-01T04:04:14.257Z","avatar_url":"https://github.com/aayushxrj.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Todo Spring Boot + Flutter\n\nMonorepo with a Spring Boot backend, a Spring Boot todos service, and a Flutter web frontend. Auth is handled by Ory Kratos for end users, and service-to-service auth uses Ory Hydra with client credentials. Observability is included via Prometheus + Grafana.\n\n## Prerequisites\n\n- Docker Desktop\n- Java 26 (for local Spring Boot development)\n- Flutter SDK (for local Flutter development)\n- kubectl + minikube (for Kubernetes)\n- Helm (for Prometheus + Grafana on Kubernetes)\n\n## Project layout\n\n- todo-springboot/ - Spring Boot backend (API gateway + auth + orchestration)\n- todos-list/ - Spring Boot todos service (DB-backed todos + resource server)\n- todo_flutter/ - Flutter web frontend\n- kratos/ - Ory Kratos config + identity schema\n- hydra/ - Ory Hydra config\n- docker-compose.yml - Docker Compose stack\n- kubernetes/ - Kubernetes manifests\n- prometheus/ - Prometheus and Grafana config\n\n## Architecture overview\n\n### Components\n\n- Flutter web (todo_flutter)\n  - UI for login, registration, and task management\n  - Uses Kratos sessions (X-Session-Token) for auth when calling backend\n\n- Backend (todo-springboot)\n  - Terminates user auth by calling Kratos /sessions/whoami\n  - Enforces method-level access control\n  - Calls todos-list via Feign\n  - Gets OAuth2 access tokens from Hydra via client credentials\n\n- Todos service (todos-list)\n  - CRUD for tasks using MySQL\n  - OAuth2 Resource Server that validates JWTs via Hydra JWKS\n\n- Ory Kratos\n  - User identity, login, and registration flows\n  - Returns session tokens and identity traits (role)\n\n- Ory Hydra\n  - OAuth2 server for service-to-service calls\n  - Issues JWT access tokens to todo-springboot\n  - Exposes JWKS for todos-list validation\n\n- MySQL\n  - Shared database for todo data (todos-list)\n\n### Request flow summary\n\n1. User logs in or registers in Flutter.\n2. Flutter calls backend /auth/kratos/* endpoints (proxy to Kratos).\n3. Backend receives the Kratos session token and stores it in the client (Flutter).\n4. Flutter calls backend /tasks with X-Session-Token.\n5. Backend validates session with Kratos /sessions/whoami and builds the Spring Security context.\n6. Backend requests a Hydra access token (client credentials) and calls todos-list via Feign.\n7. todos-list validates the JWT using Hydra JWKS and returns the tasks.\n\n## Authentication and authorization\n\n### Kratos flow (end-user)\n\nThe backend validates user sessions through Kratos so the frontend never talks to Kratos directly in production.\n\n- Login/register endpoints (backend):\n  - POST /auth/kratos/login\n  - POST /auth/kratos/register\n- Session validation (backend):\n  - Kratos /sessions/whoami\n- Roles:\n  - Stored in Kratos identity traits (role: admin|user)\n  - Mapped to ROLE_ADMIN or ROLE_USER in the backend filter\n\nFlutter uses X-Session-Token headers for authenticated requests.\n\n### Hydra flow (service-to-service)\n\ntodo-springboot uses OAuth2 client credentials to get an access token from Hydra and calls todos-list with Authorization: Bearer \u003ctoken\u003e.\n\n- Token request: POST http://hydra:4444/oauth2/token\n- JWKS endpoint (todos-list uses this): http://hydra:4444/.well-known/jwks.json\n\nHydra client setup (example):\n\n```sh\ncurl -i -X POST http://localhost:4445/admin/clients \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"client_id\": \"todos-service\",\n    \"client_secret\": \"change-me\",\n    \"grant_types\": [\"client_credentials\"],\n    \"response_types\": [\"token\"],\n    \"token_endpoint_auth_method\": \"client_secret_basic\",\n    \"scope\": \"todos.read\",\n    \"audience\": [\"todos-list\"]\n  }'\n```\n\n## OpenFeign integration\n\ntodo-springboot uses OpenFeign to call todos-list. A Feign RequestInterceptor adds the Hydra Bearer token for each request.\n\n- Token acquisition: HydraTokenService\n- Feign interceptor: TodosListClientConfig\n- todos-list base URL: TODOSLIST_BASE_URL\n\n## Service ports\n\n- Frontend: http://localhost:8081\n- Backend: http://localhost:9191\n- todos-list: http://localhost:8082\n- Hydra public: http://localhost:4444\n- Hydra admin: http://localhost:4445\n- Kratos public: http://localhost:4433\n- Kratos admin: http://localhost:4434\n- Prometheus: http://localhost:9090\n- Grafana: http://localhost:3000\n\n## Configuration keys (Docker Compose)\n\nThese are the main environment variables used in the stack:\n\n- todo-springboot\n  - PERMIFY_BASE_URL\n  - PERMIFY_TENANT_ID\n  - TODOSLIST_BASE_URL\n  - kratos.public-base-url\n  - hydra.public-base-url\n  - hydra.client-id\n  - hydra.client-secret\n  - hydra.scope\n  - hydra.audience\n\n- todos-list\n  - SPRING_DATASOURCE_URL\n  - SPRING_DATASOURCE_USERNAME\n  - SPRING_DATASOURCE_PASSWORD\n  - spring.security.oauth2.resourceserver.jwt.jwk-set-uri\n\n## Get started (Docker Compose)\n\n1. Build and run the stack:\n   ```sh\n   docker compose up --build\n   ```\n2. Open the app:\n   - Frontend: http://localhost:8081\n   - Backend: http://localhost:9191\n3. Stop the stack:\n   ```sh\n   docker compose down\n   ```\n\n## Get started (Kubernetes with Minikube)\n\n1. Start Minikube:\n   ```sh\n   minikube start\n   ```\n2. Use Minikube Docker daemon (so images are visible inside the cluster):\n   ```sh\n   eval $(minikube docker-env)\n   ```\n3. Build images:\n   ```sh\n   docker build -t todo-springboot:latest ./todo-springboot\n   docker build -t todos-list:latest ./todos-list\n   docker build -t todo-flutter-web:latest ./todo_flutter\n   ```\n4. Apply manifests:\n   ```sh\n   kubectl apply -f kubernetes/\n   ```\n5. Access the frontend:\n   ```sh\n   minikube service todo-frontend\n   ```\n\n## Observability (Prometheus + Grafana)\n\n### Install on Kubernetes using Helm\n\n1. Add the Helm repo:\n   ```sh\n   helm repo add prometheus-community https://prometheus-community.github.io/helm-charts\n   helm repo update\n   ```\n2. Create the namespace:\n   ```sh\n   kubectl create namespace monitoring\n   ```\n3. Install kube-prometheus-stack:\n   ```sh\n   helm install monitoring prometheus-community/kube-prometheus-stack -n monitoring\n   ```\n4. Port-forward Grafana:\n   ```sh\n   kubectl -n monitoring port-forward svc/monitoring-grafana 3000:80\n   ```\n5. Open Grafana:\n   - http://localhost:3000\n   - Default user: admin\n   - Default password:\n     ```sh\n     kubectl -n monitoring get secret monitoring-grafana -o jsonpath=\"{.data.admin-password}\" | base64 --decode\n     ```\n6. Port-forward Prometheus:\n   ```sh\n   kubectl -n monitoring port-forward svc/monitoring-kube-prometheus-prometheus 9090:9090\n   ```\n7. Open Prometheus:\n   - http://localhost:9090\n\n### Uninstall\n\n```sh\nhelm uninstall monitoring -n monitoring\n```\n\n## Notes\n\n- The backend expects MySQL at service name \"mysql\" in Kubernetes.\n- If you use Docker Compose only, MySQL is included in docker-compose.yml.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faayushxrj%2Ftodo-springboot-flutter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faayushxrj%2Ftodo-springboot-flutter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faayushxrj%2Ftodo-springboot-flutter/lists"}