Keycloak — Configuración Fase 1¶
Realm:
iris· Host:https://auth.huellagenica.com
1. Realm roles¶
Roles nativos de Postgres creados en Realm roles:
Roles simples, no composite. Se asignan directamente desde los grupos.
2. Grupos y atributos¶
Jerarquía de grupos creada en Groups:
/iris-internal/¶
| Subgrupo | Atributos | Realm role asignado |
|---|---|---|
bioinformatician |
all_orgs=false |
bioinformatician |
bioinformatician-admin |
all_orgs=true |
bioinformatician |
employee |
— | employee |
/orgs/¶
Grupo padre sin subgrupos ni atributos. Los subgrupos se crean dinámicamente desde iris.api vía Keycloak Admin API cuando se registra una organización.
Estructura dinámica por org:
/orgs/{org_id}/
admin → sub_role=admin, org_id={id}, realm role: org_member
clinician → sub_role=clinician, org_id={id}, realm role: org_member
requester → sub_role=requester, org_id={id}, realm role: org_member
viewer → sub_role=viewer, org_id={id}, realm role: org_member
/patients/¶
Grupo raíz sin subgrupos.
| Grupo | Realm role asignado |
|---|---|
patients |
patient |
3. Protocol Mappers¶
Configurados en Client scopes → roles → Mappers.
Se heredan en todos los clients del realm.
Mappers existentes (por defecto — no modificar)¶
| Name | Type | Notas |
|---|---|---|
audience resolve |
Audience Resolve | intacto |
client roles |
User Client Role | intacto |
realm roles |
User Realm Role | Token Claim Name: role, Multivalued: Off, Claim JSON Type: String |
El mapper
realm rolesya venía configurado correctamente conToken Claim Name: role. PostgREST requiere el claimroleen el nivel raíz como string simple, no como array anidado.
Mappers creados (atributos custom)¶
| Name | Type | Token Claim Name | Claim JSON Type | Multivalued |
|---|---|---|---|---|
org_id |
User Attribute | org_id |
long |
OFF |
sub_role |
User Attribute | sub_role |
String |
OFF |
all_orgs |
User Attribute | all_orgs |
boolean |
OFF |
patient_id |
User Attribute | patient_id |
long |
OFF |
Todos con Add to ID token: ON, Add to access token: ON, Add to userinfo: ON.
4. Clients¶
iris-api — Resource server¶
| Campo | Valor |
|---|---|
| Client type | OpenID Connect |
| Client authentication | ON |
| Standard flow | OFF |
| Direct access grants | OFF |
| Service accounts roles | OFF |
| Device Authorization Grant | OFF |
Bearer-only. Solo valida tokens, nunca inicia flujos de login.
iris-genomics-cli — CLI + pipelines¶
| Campo | Valor |
|---|---|
| Client type | OpenID Connect |
| Client authentication | ON |
| Standard flow | OFF |
| Direct access grants | OFF |
| Service accounts roles | ON |
| Device Authorization Grant | ON |
Service accounts roles: ONhabilitaclient_credentialspara pipelines automatizados.Device Authorization Grant: ONhabilitadevice_flowpara uso interactivo en terminal.
backapp-genomics — BACKAPP genómica¶
| Campo | Valor |
|---|---|
| Client type | OpenID Connect |
| Client authentication | ON |
| Standard flow | ON |
| Root URL | http://localhost:8081 |
| Valid redirect URIs | http://localhost:8081/* |
| Web origins | http://localhost:8081 |
backapp-erm — BACKAPP ERM¶
| Campo | Valor |
|---|---|
| Client type | OpenID Connect |
| Client authentication | ON |
| Standard flow | ON |
| Root URL | http://localhost:8082 |
| Valid redirect URIs | http://localhost:8082/* |
| Web origins | http://localhost:8082 |
crm — CRM¶
| Campo | Valor |
|---|---|
| Client type | OpenID Connect |
| Client authentication | ON |
| Standard flow | ON |
| Root URL | http://localhost:8083 |
| Valid redirect URIs | http://localhost:8083/* |
| Web origins | http://localhost:8083 |
5. Mapper de Audience por client¶
El claim aud debe incluir iris-api para que PostgREST valide correctamente los tokens.
Se agrega como mapper en el dedicated scope de cada client (no en el realm).
Ruta: Clients → {client} → Client scopes → {client}-dedicated → Mappers → Add mapper → Audience
| Campo | Valor |
|---|---|
| Name | iris-api-audience |
| Included Client Audience | iris-api |
| Add to ID token | OFF |
| Add to access token | ON |
Aplicado en los siguientes clients:
-
iris-genomics-cli -
backapp-genomics -
backapp-erm -
crm
6. Verificación del JWT¶
Token de prueba obtenido via device_flow con usuario test-bio (grupo /iris-internal/bioinformatician):
{
"iss": "https://auth.huellagenica.com/realms/iris",
"aud": ["iris-api", "account"],
"azp": "iris-genomics-cli",
"scope": "openid profile email",
"role": "bioinformatician",
"all_orgs": false,
"email_verified": true,
"preferred_username": "test-bio"
}
Claims validados¶
| Claim | Valor | Estado |
|---|---|---|
role |
bioinformatician |
✅ realm role como string simple |
all_orgs |
false |
✅ atributo de grupo como boolean |
aud |
["iris-api", "account"] |
✅ audience correcto para PostgREST |
iss |
https://auth.huellagenica.com/realms/iris |
✅ issuer correcto |
org_idysub_roleausentes en este token — esperado. El grupo/iris-internal/bioinformaticianno tieneorg_idasignado. Aparecerán cuando el usuario pertenezca a un subgrupo de/orgs/{org_id}/.
Comandos de prueba¶
Device flow (interactivo)¶
# Paso 1 — solicitar device code
curl -s -X POST \
https://auth.huellagenica.com/realms/iris/protocol/openid-connect/auth/device \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=iris-genomics-cli" \
-d "client_secret=<client_secret>" \
-d "scope=openid"
# Abrir verification_uri_complete en el navegador y autenticarse
# Paso 2 — obtener y decodificar token
curl -s -X POST \
https://auth.huellagenica.com/realms/iris/protocol/openid-connect/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=urn:ietf:params:oauth:grant-type:device_code" \
-d "device_code=<device_code>" \
-d "client_id=iris-genomics-cli" \
-d "client_secret=<client_secret>" \
| python3 -c "
import sys, json, base64
token = json.load(sys.stdin)['access_token']
payload = token.split('.')[1]
payload += '=' * (4 - len(payload) % 4)
print(json.dumps(json.loads(base64.b64decode(payload)), indent=2))
"