diff --git a/README.MD b/README.MD index 50082bca..a3156f49 100644 --- a/README.MD +++ b/README.MD @@ -1,42 +1,55 @@ # FAF User Service -This service aims to cover the domain of login and account management in FAForever. +This service aims to cover the domain of login and account management in FAForever: +* OAuth 2.0 / OIDC login backend for Ory Hydra +* IRC login for Ergochat +* User Control Panel with manual login -## Technology stack +## Developer information + +### Technology stack - Kotlin - Quarkus - Hibernate (Panache) - Vaadin +### Dependencies -## Motivation and architecture considerations +The FAF user service requires +* A [MariaDB](https://mariadb.org/) server running a matching version of the [faf-db](https://github.com/FAForever/db). (Latest develop should always work) +* An [Ory Hydra](https://github.com/ory/hydra) server running in a matching version -### Yet another FAF API? +### Developer setup + +For local development you need +* a working Kotlin setup (e.g. install IntelliJ Community and download the required JDK from IntellIJ directly) +* Docker Compose + +Setup all docker depencies along with test data by simply running: +```shell +docker compose up -d +``` +This will insert the faf db testdata into the faf-db and a faf-client OAuhth client into Ory Hydra. -> The faf-java-api already offers OAuth2 login and user management. Why do we need yet another service? -There are multiple reasons that led to this decision: +Hint: The docker compose stack is **not** persisting to disk. Deleting containers manually or via `docker compose down` will wipe all data. + +## Architecture considerations + +### Yet another FAF API? -1. **Application perspective:** The faf-java-api uses the - [Spring Security OAuth](https://spring.io/projects/spring-security-oauth) library. - 1. With the release of Spring 5 this got deprecated in favour of a newer one. Unfortunately with this transition - the support for OAuth2 identity server was dropped completely. It receives no more updates. - 1. Since the library is deprecated we lack support for the improved OAuth2 PKCE login flow, which improves overall - security compared to the previous implicit flow. - 1. The current library seems to have issues when trying to login with certified libraries from the Angular ecosystem. - It just doesn't work in some cases, where we need it to work. (But nobody will fix it since it's deprecated.) -2. **Architecture perspective:** The faf-java-api is the FAF swiss army knife. It basically bundles every feature +1. **Architecture perspective:** The faf-java-api is the FAF swiss army knife. It basically bundles every feature outside of the lobby server protocol. This makes it very complex to maintain and configure. It also causes very high startup times causing unnecessary downtimes on deployments. This does not match our desired architecture. A new microservice focussing on one particular topic (and security is a very important topic which is also hard to get right) simplifies that. -3. **GDPR and DevOps implications:** Currently FAF runs almost all applications on one server. An admin on that server +1. **GDPR and DevOps implications:** Currently FAF runs almost all applications on one server. An admin on that server has access to all personal data. Adding new admins is a large hassle due to GDPR requirements. Due to this many FAF maintainers have no access to their application logs and configuration, which makes fixing bugs etc. much more complicated and adds additional work onto the few admins. This new service might be a first step into moving the whole account management out of the main server. -4. **Long running perspective:** In a perfect world we would migrate all authorization related stuff into a dedicated +1. **Long running perspective:** In a perfect world we would migrate all authorization related stuff into a dedicated (trusted) 3rd party software, so we can't mess up on security. ### Additional goals diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 00000000..5439f70c --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,106 @@ +services: + # Set up the faf db + faf-db: + image: mariadb:11 + environment: + MARIADB_DATABASE: faf + MARIADB_USER: faf-user-service + MARIADB_PASSWORD: banana + MARIADB_ROOT_PASSWORD: banana + healthcheck: + test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] + interval: 10s + timeout: 5s + retries: 5 + ports: + - "3306:3306" + + faf-db-migrations: + image: faforever/faf-db-migrations:v135 + command: migrate + environment: + FLYWAY_URL: jdbc:mysql://faf-db/faf?useSSL=false + FLYWAY_USER: root + FLYWAY_PASSWORD: banana + FLYWAY_DATABASE: faf + depends_on: + faf-db: + condition: service_healthy + + faf-db-testdata: + image: mariadb:11 + entrypoint: sh -c "apt-get update && apt-get install -y curl && curl -s https://raw.githubusercontent.com/FAForever/db/refs/heads/develop/test-data.sql | mariadb -h faf-db -uroot -pbanana -D faf" + depends_on: + faf-db-migrations: + condition: service_completed_successfully + + hydra-db: + image: postgres:16 + environment: + - POSTGRES_USER=hydra + - POSTGRES_PASSWORD=banana + - POSTGRES_DB=hydra + healthcheck: + test: ["CMD-SHELL", "pg_isready", "-U", "postgres"] + interval: 10s + timeout: 5s + retries: 5 + + hydra-migrate: + image: oryd/hydra:v1.11.10 + command: migrate -c /etc/config/hydra/hydra.yml sql -e --yes + environment: + - DSN=postgres://hydra:banana@hydra-db:5432/hydra?sslmode=disable + volumes: + - type: bind + source: ./hydra.yml + target: /etc/config/hydra/hydra.yml + depends_on: + hydra-db: + condition: service_healthy + + hydra: + image: oryd/hydra:v1.11.10 + ports: + - "4444:4444" # Public port + - "4445:4445" # Admin port + command: serve -c /etc/config/hydra/hydra.yml all --dangerous-force-http + environment: + - DSN=postgres://hydra:banana@hydra-db:5432/hydra?sslmode=disable + volumes: + - type: bind + source: ./hydra.yml + target: /etc/config/hydra/hydra.yml + depends_on: + hydra-db: + condition: service_healthy + hydra-migrate: + condition: service_completed_successfully + healthcheck: + test: ["CMD-SHELL", "hydra", "clients", "list", "--endpoint", "http://hydra:4445"] + interval: 10s + timeout: 5s + retries: 5 + + hydra-testdata: + image: oryd/hydra:v1.11.10 + entrypoint: > + hydra clients create + --skip-tls-verify + --endpoint http://hydra:4445 + --fake-tls-termination + --id faf-client + --name faf-client + --logo-uri https://faforever.com/images/faf-logo.png + --grant-types authorization_code,refresh_token + --response-types code + --scope openid,offline,public_profile,lobby,upload_map,upload_mod + --callbacks http://localhost + --token-endpoint-auth-method none + depends_on: + hydra: + condition: service_healthy + hydra-migrate: + condition: service_completed_successfully + + diff --git a/hydra.yml b/hydra.yml new file mode 100644 index 00000000..a06f87cb --- /dev/null +++ b/hydra.yml @@ -0,0 +1,23 @@ +# Config file for Hydra in docker-compose.yaml +serve: + cookies: + same_site_mode: Lax + +urls: + self: + issuer: http://127.0.0.1:4444 + consent: http://127.0.0.1:3000/consent + login: http://127.0.0.1:3000/login + logout: http://127.0.0.1:3000/logout + +secrets: + system: + - bananapineapplepizza + +oidc: + subject_identifiers: + supported_types: + - pairwise + - public + pairwise: + salt: bananapineapplepizza \ No newline at end of file