kych

OAuth 2.0 API for Swiyu to enable Taler integration of Swiyu for KYC (experimental)
Log | Files | Refs

commit adbfddb6fba080c242b7d122d252c6ba75231dc9
parent 3c748c658c9f540da28c4d72910bb98aea4fc52d
Author: Henrique Chan Carvalho Machado <henriqueccmachado@tecnico.ulisboa.pt>
Date:   Sat, 22 Nov 2025 18:00:39 +0100

documentation: add sequence diagrams for oauth2 gateway api endpoints

Diffstat:
Adocumentation/sequence_diagrams/authorize_sequence.txt | 38++++++++++++++++++++++++++++++++++++++
Adocumentation/sequence_diagrams/info_sequence.txt | 30++++++++++++++++++++++++++++++
Adocumentation/sequence_diagrams/notification_sequence.txt | 41+++++++++++++++++++++++++++++++++++++++++
Adocumentation/sequence_diagrams/setup_sequence.txt | 22++++++++++++++++++++++
Adocumentation/sequence_diagrams/swiyu_taler_sequence_diagram.txt | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Adocumentation/sequence_diagrams/token_sequence.txt | 42++++++++++++++++++++++++++++++++++++++++++
6 files changed, 222 insertions(+), 0 deletions(-)

diff --git a/documentation/sequence_diagrams/authorize_sequence.txt b/documentation/sequence_diagrams/authorize_sequence.txt @@ -0,0 +1,37 @@ +sequenceDiagram + participant Client + participant OAuth2 Gateway + participant OAuth2 Gateway DB + participant Swiyu Verifier + + Client ->> OAuth2 Gateway: GET /authorize?\nresponse_type=code&\nclient_id={client_id}&\nnonce={nonce} + + OAuth2 Gateway ->> OAuth2 Gateway: Validate parameters:\n- response_type == 'code' + + alt Invalid parameters + OAuth2 Gateway -->> Client: 400 BAD REQUEST\n{error: 'invalid_request'} + else Valid parameters + OAuth2 Gateway ->> OAuth2 Gateway DB: UPDATE verification_sessions s \nSET status = s.status \nFROM clients c \nWHERE s.client_id = c.id \nAND s.nonce = $1 AND c.client_id = $2 \nRETURNING s.id, s.status, s.expires_at, \ns.scope, s.verification_url, \ns.request_id, s.verifier_nonce, \nc.verifier_url, c.verifier_management_api_path + + OAuth2 Gateway DB -->> OAuth2 Gateway: Query result + end + + alt Session error + OAuth2 Gateway -->> Client: Error Response:\n- 404 NOT FOUND (session not found)\n- 410 GONE (expired)\n- 409 CONFLICT (not pending) + else Session already authorized (idempotent) + OAuth2 Gateway -->> Client: 200 OK \n{verification_id, verification_url} + else Session valid and pending - proceed + OAuth2 Gateway ->> OAuth2 Gateway: build_presentation_definition(scope) + + OAuth2 Gateway ->> Swiyu Verifier: POST /management/api/verifications \n{presentation_definition, response_mode, ...} + Swiyu Verifier -->> OAuth2 Gateway: Response + + alt Error + OAuth2 Gateway -->> Client: Error Response:\n- 502 BAD GATEWAY (verifier error)\n- 500 INTERNAL SERVER ERROR (DB error) + else Success + OAuth2 Gateway ->> OAuth2 Gateway DB: UPDATE verification_sessions \nSET verification_url = $1, request_id = $2, \nverifier_nonce = $3, status = 'authorized', \nauthorized_at = NOW() \nWHERE id = $4 \nRETURNING verification_url, request_id + + OAuth2 Gateway DB -->> OAuth2 Gateway: Updated session + OAuth2 Gateway -->> Client: 200 OK \n{verification_id, verification_url} + end + end +\ No newline at end of file diff --git a/documentation/sequence_diagrams/info_sequence.txt b/documentation/sequence_diagrams/info_sequence.txt @@ -0,0 +1,29 @@ +sequenceDiagram + participant Client + participant OAuth2 Gateway + participant OAuth2 Gateway DB + + Client ->> OAuth2 Gateway: GET /info \nAuthorization: Bearer <token> + + OAuth2 Gateway ->> OAuth2 Gateway: Extract token from \nAuthorization header + + alt Missing or malformed Authorization header + OAuth2 Gateway -->> Client: 401 UNAUTHORIZED \n{error: 'invalid_token'} + else Valid header format + OAuth2 Gateway ->> OAuth2 Gateway DB: UPDATE access_tokens t \nSET revoked = t.revoked \nFROM verification_sessions s \nWHERE t.session_id = s.id \nAND t.token = $1 \nAND t.expires_at > NOW() \nRETURNING t.revoked, s.status, \ns.verifiable_credential + + alt Token not found or expired + OAuth2 Gateway DB -->> OAuth2 Gateway: 0 rows + OAuth2 Gateway -->> Client: 401 UNAUTHORIZED \n{error: 'invalid_token'} + else Token found + OAuth2 Gateway DB -->> OAuth2 Gateway: token and session data + + OAuth2 Gateway ->> OAuth2 Gateway: Validate:\n- not revoked\n- status == 'completed' + + alt Invalid token state + OAuth2 Gateway -->> Client: 401 UNAUTHORIZED \n{error: 'invalid_token'} + else Valid token and VC available + OAuth2 Gateway -->> Client: 200 OK \n{verifiable_credential} + end + end + end +\ No newline at end of file diff --git a/documentation/sequence_diagrams/notification_sequence.txt b/documentation/sequence_diagrams/notification_sequence.txt @@ -0,0 +1,40 @@ +sequenceDiagram + participant Swiyu Verifier + participant OAuth2 Gateway + participant OAuth2 Gateway DB + + note over Swiyu Verifier,OAuth2 Gateway DB: Incoming Webhook from Swiyu + + Swiyu Verifier ->> OAuth2 Gateway: POST /notification \n{verification_id, timestamp} + + OAuth2 Gateway ->> OAuth2 Gateway DB: UPDATE verification_sessions s \nSET status = s.status \nFROM clients c \nWHERE s.client_id = c.id \nAND s.request_id = $1 \nRETURNING s.id, s.nonce, s.status, \nc.id AS client_id, c.webhook_url, \nc.verifier_url, c.verifier_management_api_path + + alt DB error or session invalid + OAuth2 Gateway DB -->> OAuth2 Gateway: Error / 0 rows + OAuth2 Gateway ->> OAuth2 Gateway: Log error\n- DB connection failed\n- Session not found\n- Session not authorized\n- Session already processed + OAuth2 Gateway -->> Swiyu Verifier: 200 OK + else Session found + OAuth2 Gateway DB -->> OAuth2 Gateway: session + client data + + OAuth2 Gateway ->> OAuth2 Gateway: Validate session (status == 'authorized') + + alt Session invalid + OAuth2 Gateway ->> OAuth2 Gateway: Log error\n- Session not authorized\n- Session already processed + OAuth2 Gateway -->> Swiyu Verifier: 200 OK + else Session valid + OAuth2 Gateway ->> Swiyu Verifier: GET verifier_url + verifier_management_api_path + /verification_id + Swiyu Verifier -->> OAuth2 Gateway: {status: 'verified'/'failed', ...} + + OAuth2 Gateway ->> OAuth2 Gateway: generate_authorization_code() + + OAuth2 Gateway ->> OAuth2 Gateway DB: WITH updated AS (\n UPDATE verification_sessions \n SET status = $1, verified_at = NOW() \n WHERE id = $2 RETURNING id\n),\ninserted_code AS (\n INSERT INTO authorization_codes \n (session_id, code, expires_at) \n VALUES ($2, $3, NOW() + INTERVAL '10 minutes') \n RETURNING code\n)\nINSERT INTO notification_pending_webhooks \n(session_id, client_id, url, body, next_attempt) \nSELECT $2, $4, $5, $6, 0 + + alt Operation failed + OAuth2 Gateway ->> OAuth2 Gateway: Log error\n- Verifier fetch failed\n- DB update failed\n- Code generation failed\n- Queue insert failed + else Success + OAuth2 Gateway DB ->> OAuth2 Gateway DB: TRIGGER\nNotifies Worker Thread\nfor Client Webhooks + OAuth2 Gateway DB -->> OAuth2 Gateway: OK + end + end + OAuth2 Gateway -->> Swiyu Verifier: 200 OK + end +\ No newline at end of file diff --git a/documentation/sequence_diagrams/setup_sequence.txt b/documentation/sequence_diagrams/setup_sequence.txt @@ -0,0 +1,21 @@ +sequenceDiagram + participant Client + participant OAuth2 Gateway + participant OAuth2 Gateway DB + + Client ->> OAuth2 Gateway: POST /setup/{client_id}\n{scope: "first_name last_name"} + + OAuth2 Gateway ->> OAuth2 Gateway: generate_nonce()\n(256-bit CSPRNG) + + OAuth2 Gateway ->> OAuth2 Gateway DB: INSERT INTO verification_sessions\n(client_id, nonce, scope, expires_at)\nSELECT c.id, $1, $2, NOW() + INTERVAL '15 minutes'\nFROM clients c WHERE c.client_id = $3\nRETURNING id, nonce, expires_at + + alt Client not found + OAuth2 Gateway DB -->> OAuth2 Gateway: 0 rows + OAuth2 Gateway -->> Client: 404 NOT FOUND\n{error: "client_not_found"} + else DB error + OAuth2 Gateway DB -->> OAuth2 Gateway: Error + OAuth2 Gateway -->> Client: 500 INTERNAL SERVER ERROR + else Success + OAuth2 Gateway DB -->> OAuth2 Gateway: session {id, nonce, expires_at} + OAuth2 Gateway -->> Client: 200 OK {nonce} + end +\ No newline at end of file diff --git a/documentation/sequence_diagrams/swiyu_taler_sequence_diagram.txt b/documentation/sequence_diagrams/swiyu_taler_sequence_diagram.txt @@ -0,0 +1,49 @@ +sequenceDiagram + title Swiyu-Taler Interaction + + participant Browser + participant TalerWallet + participant Exchange + participant Oauth2Gateway + participant SwiyuVerifier + participant SwiyuWallet + + TalerWallet ->> Exchange: Initiate KYC-required operation + Exchange -->> TalerWallet: Send verification link + TalerWallet ->> Browser: Open link + Browser ->> Exchange: Select verification method (Swiyu) + + note over Exchange,Oauth2Gateway: Exchange initiates KYC verification process + Exchange ->> Oauth2Gateway: POST /setup/$CLIENT_ID + Oauth2Gateway -->> Exchange: $NONCE + Exchange ->> Browser: Send /authorize endpoint + + Browser ->> Oauth2Gateway: GET /authorize/$NONCE... + Oauth2Gateway ->> SwiyuVerifier: POST /management/api/verifications + SwiyuVerifier -->> Oauth2Gateway: $VERIFICATION_URL, $REQUEST_ID + Oauth2Gateway -->> Browser: Send $VERIFICATION_URL + + Browser ->> Oauth2Gateway: Poll Verification Status + Browser ->> SwiyuWallet: Open $VERIFICATION_URL + SwiyuWallet ->> SwiyuVerifier: GET /oid4vp/api/request-object/{request_id} + SwiyuVerifier -->> SwiyuWallet: OID4VP Request Object (DCQL query) + SwiyuWallet ->> SwiyuWallet: Grant Permission + SwiyuWallet ->> SwiyuVerifier: POST /oid4vp/api/request-object/{request_id}/response-data (VP Token) + + note over Oauth2Gateway,Exchange: Oauth2Gateway receives webhook and retrieves swiyu wallet response + SwiyuVerifier ->> Oauth2Gateway: POST /notification {verification_id, timestamp} + Oauth2Gateway ->> SwiyuVerifier: GET /management/api/verifications/{verification_id} + SwiyuVerifier -->> Oauth2Gateway: {state: SUCCESS/FAILED, wallet_response} + Oauth2Gateway -->> Browser: Notify verification result + Oauth2Gateway ->> Exchange: POST /oauth2gw/kyc/notify/$CLIENT_ID {status} + + note over Exchange,Oauth2Gateway: Exchange retrieves the final proof (Verifiable Credential) + Exchange ->> Oauth2Gateway: POST /token + Oauth2Gateway -->> Exchange: Access token + Exchange ->> Oauth2Gateway: GET /info (with access token) + Oauth2Gateway ->> SwiyuVerifier: GET /management/api/verifications/{verificationId} + SwiyuVerifier -->> Oauth2Gateway: Send proof (Verifiable Credential) + Oauth2Gateway -->> Exchange: Send proof (in response body) + + Exchange -->> TalerWallet: Notify success + TalerWallet ->> Exchange: Retry original operation diff --git a/documentation/sequence_diagrams/token_sequence.txt b/documentation/sequence_diagrams/token_sequence.txt @@ -0,0 +1,41 @@ +sequenceDiagram + participant Client + participant OAuth2 Gateway + participant OAuth2 Gateway DB + + Client ->> OAuth2 Gateway: POST /token \n{code, grant_type} + + OAuth2 Gateway ->> OAuth2 Gateway: Validate grant_type == \n'authorization_code' + + alt Invalid grant type + OAuth2 Gateway -->> Client: 400 BAD REQUEST \n{error: 'unsupported_grant_type'} + else Valid grant type + OAuth2 Gateway ->> OAuth2 Gateway DB: WITH code_data AS (\n SELECT id, used AS was_already_used, session_id\n FROM authorization_codes\n WHERE code = $1 AND expires_at > NOW()\n FOR UPDATE\n),\nupdated_code AS (\n UPDATE authorization_codes ac\n SET used = TRUE,\n used_at = CASE WHEN NOT ac.used THEN NOW() ELSE ac.used_at END\n FROM code_data cd\n WHERE ac.id = cd.id\n RETURNING ac.id, ac.session_id\n)\nSELECT uc.id AS code_id,\n cd.was_already_used,\n uc.session_id,\n vs.status AS session_status,\n at.token AS existing_token,\n at.expires_at AS token_expires_at\nFROM updated_code uc\nJOIN code_data cd ON uc.id = cd.id\nJOIN verification_sessions vs ON vs.id = uc.session_id\nLEFT JOIN access_tokens at\n ON at.session_id = vs.id AND at.revoked = FALSE + + alt No code found or DB error + OAuth2 Gateway DB -->> OAuth2 Gateway: 0 rows / Error + OAuth2 Gateway -->> Client: Error Response:\n- 400 BAD REQUEST {error: 'invalid_grant'}\n- 500 INTERNAL SERVER ERROR + else Code found + OAuth2 Gateway DB -->> OAuth2 Gateway: code, session, and token data + + OAuth2 Gateway ->> OAuth2 Gateway: Check state + + alt Token already exists (idempotent) + OAuth2 Gateway -->> Client: 200 OK \n{access_token: existing_token, \ntoken_type: 'Bearer', expires_in: 3600} + else Invalid state + OAuth2 Gateway -->> Client: 400 BAD REQUEST \n{error: 'invalid_grant'}\n- Code already used\n- Session not verified + else Valid - create token + OAuth2 Gateway ->> OAuth2 Gateway: generate_access_token() + + OAuth2 Gateway ->> OAuth2 Gateway DB: WITH updated AS (\n UPDATE verification_sessions \n SET status = 'completed', completed_at = NOW() \n WHERE id = $1 RETURNING id\n)\nINSERT INTO access_tokens \n(session_id, token, expires_at) \nVALUES ($1, $2, NOW() + INTERVAL '1 hour') \nRETURNING token, expires_at + + alt Error + OAuth2 Gateway DB -->> OAuth2 Gateway: Error + OAuth2 Gateway -->> Client: 500 INTERNAL SERVER ERROR + else Success + OAuth2 Gateway DB -->> OAuth2 Gateway: token, expires_at + OAuth2 Gateway -->> Client: 200 OK \n{access_token, token_type: 'Bearer', expires_in: 3600} + end + end + end + end +\ No newline at end of file