# Task Management API — Test Procedure ## Overview The API is exposed at `https://gateway.gravitee.sttlab.pc/tasks-management`. Two OAuth2 / OIDC flows are supported, both validated via Keycloak realm `sttlab`. | Flow | Client | Grant type | Use case | |---|---|---|---| | OAuth2 client credentials | `test-backend` | `client_credentials` | Service-to-service | | OIDC Authorization Code + PKCE | `test-app` | `authorization_code` | User-facing app | --- ## Prerequisites - `/etc/hosts` entry: `192.168.1.18 gateway.gravitee.sttlab.pc` - Keycloak reachable at `https://keycloak.sttlab.eu` - Gravitee Gateway running (`gravitee-apim` namespace) Set the following environment variables before running the commands below: ```bash export TEST_BACKEND_SECRET= export TEST_USER_PASSWORD= ``` --- ## Test 1 — OAuth2 client_credentials (test-backend) ### Step 1 — Obtain a token ```bash TOKEN=$(curl -s -X POST https://keycloak.sttlab.eu/realms/sttlab/protocol/openid-connect/token \ -d "client_id=test-backend" \ -d "client_secret=${TEST_BACKEND_SECRET}" \ -d "grant_type=client_credentials" \ -d "scope=tasks-full" \ | jq -r '.access_token') ``` To request read-only access, replace `tasks-full` with `tasks-read`. ### Step 2 — Call the API **List tasks (GET):** ```bash curl -sk https://gateway.gravitee.sttlab.pc/tasks-management/tasks \ -H "Authorization: Bearer ${TOKEN}" ``` Expected: `HTTP 200` with a JSON array of tasks. **Create a task (POST):** ```bash curl -sk -X POST https://gateway.gravitee.sttlab.pc/tasks-management/tasks \ -H "Authorization: Bearer ${TOKEN}" \ -H "Content-Type: application/json" \ -d '{"description": "Test task"}' ``` Expected: `HTTP 201` with the created task. ### Step 3 — Verify rejection without token ```bash curl -sk -o /dev/null -w "%{http_code}" \ https://gateway.gravitee.sttlab.pc/tasks-management/tasks ``` Expected: `401` --- ## Test 2 — OIDC Authorization Code + PKCE (test-app / test-user) Headless flow — no browser required. Keycloak's login form is submitted directly via curl. ### Step 1 — Generate PKCE parameters ```bash CODE_VERIFIER=$(openssl rand -base64 32 | tr -d '=\n' | tr '+/' '-_') CODE_CHALLENGE=$(echo -n "${CODE_VERIFIER}" | openssl dgst -sha256 -binary | base64 | tr -d '=\n' | tr '+/' '-_') ``` ### Step 2 — Fetch the login form and extract the action URL ```bash curl -sc /tmp/kc-cookies.txt \ "https://keycloak.sttlab.eu/realms/sttlab/protocol/openid-connect/auth?response_type=code&client_id=test-app&redirect_uri=http://localhost:3000/callback&code_challenge=${CODE_CHALLENGE}&code_challenge_method=S256&scope=openid%20tasks-read" \ -o /tmp/kc-login.html LOGIN_URL=$(grep -o 'action="[^"]*"' /tmp/kc-login.html | sed 's/action="//;s/"$//;s/&/\&/g') ``` ### Step 3 — Submit credentials and capture the authorization code ```bash REDIRECT=$(curl -s -b /tmp/kc-cookies.txt -c /tmp/kc-cookies.txt \ -X POST "${LOGIN_URL}" \ -d "username=test-user&password=${TEST_USER_PASSWORD}&credentialId=" \ -D - -o /dev/null | grep -i "^location:" | tr -d '\r' | sed 's/location: //i') CODE=$(echo "${REDIRECT}" | grep -o 'code=[^&]*' | sed 's/code=//') ``` ### Step 4 — Exchange the authorization code for a token ```bash TOKEN=$(curl -s -X POST \ https://keycloak.sttlab.eu/realms/sttlab/protocol/openid-connect/token \ -d "grant_type=authorization_code" \ -d "code=${CODE}" \ -d "redirect_uri=http://localhost:3000/callback" \ -d "client_id=test-app" \ -d "code_verifier=${CODE_VERIFIER}" \ | jq -r '.access_token') ``` ### Step 5 — Inspect the token ```bash jq -R 'split(".") | .[1] | @base64d | fromjson' <<< "${TOKEN}" ``` Verify the following claims: | Claim | Expected value | |---|---| | `iss` | `https://keycloak.sttlab.eu/realms/sttlab` | | `azp` | `test-app` | | `preferred_username` | `test-user` | | `scope` | contains `tasks-read` | ### Step 6 — Call the API ```bash curl -sk https://gateway.gravitee.sttlab.pc/tasks-management/tasks \ -H "Authorization: Bearer ${TOKEN}" ``` Expected: `HTTP 200` with a JSON array of tasks. --- ## Troubleshooting | Symptom | Likely cause | |---|---| | `401 Unauthorized` | Missing or expired token — request a new one | | `401 Unauthorized` | Application not subscribed to plan — check GKO subscription | | `invalid_scope` error from Keycloak | Scope not assigned as optional on the client — check Keycloak client scopes | | Token obtained but gateway returns `401` | `azp` claim not matching any subscribed application in Gravitee |