Endpoints Machine-to-Machine do Access Management e SDK Java para chamadas entre serviços com client credentials.
Documenta a superfície Machine‑to‑Machine (M2M) do Access Management — os endpoints que outros serviços invocam com um JWT client credentials, e o SDK Java (cv.igrp.platform.access:client) que abstrai as chamadas.
Autenticação
Todas as chamadas /api/m2m/* exigem um JWT client credentials. O caller obtém‑no de:
POST /oauth2/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic <base64(clientId:clientSecret)>
grant_type=client_credentials&scope=m2mM2MTokenRejectionFilter
Um token M2M não pode ser usado para endpoints direccionados a utilizadores humanos (por exemplo, /api/users/me/*). O filtro M2MTokenRejectionFilter rejeita‑o com 403 e código M2M_TOKEN_ON_USER_ENDPOINT. Simetricamente, um JWT de utilizador não é aceite em /api/m2m/*.
Endpoints de sincronização
Utilizados pelo AuthorizationSyncRunner (framework core-spring-boot) e pelo startup-sync.ts do Next.js:
| Método + Path | Corpo | Efeito |
|---|---|---|
POST /api/m2m/sync/permissions | List<PermissionDTO> | Cria/actualiza o catálogo de permissões do caller. |
POST /api/m2m/sync/resources | ResourceDTO | Registra o caller como Resource (type=API, name=spring.application.name). |
POST /api/m2m/sync/applications | ApplicationDTO | Registra/actualiza o caller como Application. Sincroniza name, slug, type, description, status. |
POST /api/m2m/sync/applications/{code}/menus?syncRoles=true | List<MenuEntryDTO> | Sincroniza a árvore de menus da aplicação. Com syncRoles=true, também associa perfis a cada entrada. |
Endpoints de leitura
Servem para os target projects consultarem o modelo de AM sem duplicar a lógica de scoping/RBAC. Todos aceitam um corpo JSON com filtros.
| Método + Path | Corpo (filtros) | Resposta |
|---|---|---|
POST /api/m2m/users | activeOnly, applicationCode, departmentCode, roleCode, permissionName, includeChildrenDepartments, includeChildrenRoles | Lista de utilizadores filtrada. |
POST /api/m2m/departments | activeOnly, parentCode, includeChildren (recursivo) | Lista de departamentos filtrada. |
POST /api/m2m/roles | activeOnly, applicationCode, departmentCode, includeChildrenRoles | Lista de perfis filtrada. |
Exemplo — lookup de utilizadores num departamento e descendentes
POST /api/m2m/users
Authorization: Bearer <JWT client credentials>
Content-Type: application/json
{
"activeOnly": true,
"departmentCode": "DEPT_RH",
"includeChildrenDepartments": true,
"roleCode": "MANAGER"
}[
{
"id": "...",
"email": "ana@example.cv",
"preferredUsername": "ana",
"givenName": "Ana",
"familyName": "Silva",
"departmentCode": "DEPT_RH_CV",
"roles": ["MANAGER"]
}
]Aplicabilidade do âmbito
Estes endpoints são utilizados por serviços — não por gestores humanos — logo não aplicam a regra do âmbito do gestor. Se o objectivo for espelhar a experiência UI, o cliente do target project deve invocá‑los com um JWT de utilizador e por endpoints correspondentes (/api/departments/manageable, etc.).
SDK Java
Todas as chamadas M2M têm um wrapper Java. Duas classes principais:
| Classe | Responsabilidade |
|---|---|
ApiClient | Configura URL base, credenciais client_credentials, refresh do token em cache, timeouts. Reutilizável entre todos os serviços. |
M2MApi | Fachada com um método por endpoint (syncPermissions, syncResources, syncApplication, syncApplicationMenus, getUsersForBusiness, getDepartmentForBusiness, getRolesForBusiness). Thread‑safe. |
Configuração — Spring Boot
@Configuration
public class AccessMgmtM2mConfig {
@Bean
ApiClient accessMgmtApiClient(
@Value("${igrp.access.api.base-url}") String baseUrl,
@Value("${igrp.access.m2m.client-id}") String clientId,
@Value("${igrp.access.m2m.client-secret}") String clientSecret,
@Value("${igrp.access.m2m.scope:m2m}") String scope
) {
ApiClient client = new ApiClient();
client.setBaseUrl(baseUrl);
client.setClientCredentials(baseUrl, clientId, clientSecret, scope);
return client;
}
@Bean
M2MApi accessMgmtM2mApi(ApiClient client) {
return new M2MApi(client);
}
}Utilização típica
@Component
public class DepartmentSyncJob {
private final M2MApi m2m;
@Scheduled(fixedDelayString = "PT5M")
public void syncActiveManagers() {
var filter = new UsersForBusinessRequest()
.activeOnly(true)
.roleCode("MANAGER")
.includeChildrenDepartments(true);
List<UserDTO> managers = m2m.getUsersForBusiness(filter, "my-invoice-service");
managers.forEach(u -> ... );
}
}Já vem incluído pelo framework
Se o teu serviço utiliza cv.igrp.framework.auth:core-spring-boot, o AuthorizationSyncRunner já invoca syncPermissions e syncResources automaticamente no arranque. Não é necessário replicar esse código — basta ter as env vars IGRP_ACCESS_API_BASE_URL, IGRP_ACCESS_M2M_CLIENT_ID e IGRP_ACCESS_M2M_CLIENT_SECRET configuradas. Ver o Permissions Integration Guide.
Códigos de erro
| HTTP | Código | Causa comum |
|---|---|---|
| 401 | INVALID_TOKEN | JWT ausente, mal formado ou expirado. |
| 403 | M2M_TOKEN_ON_USER_ENDPOINT | JWT M2M usado num endpoint de utilizador. |
| 403 | USER_TOKEN_ON_M2M_ENDPOINT | JWT de utilizador usado em /api/m2m/*. |
| 400 | IGRP_AUTH_APPLICATION_CODE_REQUIRED | sync/applications invocado sem code. |
| 500 | IGRP_AUTH_APPLICATION_SYNC_FAILED | Falha genérica na sincronização (ver logs). |
Cross‑refs
- Overview — as env vars do M2M client no target project.
- Aplicações & Menus — o efeito de
sync/applicationsesync/applications/{code}/menus(secção de utilizador). - Departamentos & Perfis — o modelo que os endpoints de leitura devolvem (secção de utilizador).
- Âmbito do Gestor — porque estes endpoints não aplicam a mesma regra (secção de utilizador).
- Permissions Integration Guide — para o pipeline de sincronização automática via
core-spring-boot.
Última atualização:
