The iGRP Access Management API is a modular and extensible Identity and Access Management (IAM) solution designed for the iGRP Business Logic. It enables the management of users, roles, permissions, applications, and organizational structures, while also supporting integration with external IAM providers like Keycloak and WSO2 Identity Server, through an abstract adapter layer based on dependency injection.
This module provides identity, authentication, and authorization services to applications built within the iGRP ecosystem. It offers native capabilities as well as integration with external IAM providers. It can operate in standalone mode or delegate authentication/authorization to external systems, ensuring:
- Interoperability with iGRP modules
- Scalability across large infrastructures
- Compliance with modern security standards
- Features
- Architecture
- IAdapter
- Database Model
- API Endpoints
- IAM Provider Integration
- Configuration
- Running the Project
- Code Quality & Reports
- Contributing
- License
- Unified API for managing identity and access control
- Plug-and-play integration with IAM providers (Keycloak, WSO2 IS)
- Abstract adapter layer with dependency injection for extensibility
- Fine-grained role and permission management
- Departmental and application-level access control
- RESTful endpoints with secure authentication
The system is designed around a modular architecture:
- Core IAM Module: Provides core services for user, role, permission, and application management.
- IAdapter Interface: Abstracts the communication with external IAM providers.
- IAM Adapters: Implementations of
IAdapter
for providers like Keycloak and WSO2. - Dependency Injection: Ensures loose coupling between core logic and external IAM systems.
- Spring Boot: The API is built using Spring Boot with layered service and repository components.
The IAdapter
is an abstraction layer that defines the contract for IAM provider integrations. Each provider must implement this interface to ensure consistent behavior across the system.
TODO: Document available methods and usage patterns for the
IAdapter
interface.
TODO: Add diagrams and table descriptions related to:
- Applications
- Departments/OrgΓ’nicas
- Users
- Roles
- Permissions
- Resources
- Menus
- Relations among entities (e.g., user-role, role-permission)
MΓ©todo | Endpoint | Request | Response | Status Code |
---|---|---|---|---|
POST | /api/applications |
ApplicationDTO |
ApplicationDTO |
201 Created |
GET | /api/applications |
β | List<ApplicationDTO> |
200 OK |
GET | /api/applications/{id} |
β | ApplicationDTO |
200 OK |
PUT | /api/applications/{id} |
ApplicationDTO |
ApplicationDTO |
200 OK |
DELETE | /api/applications/{id} |
β | β | 204 No Content |
GET | /api/applications/denied-to-user/{uid} |
β | List<ApplicationDTO> |
200 OK |
GET | /api/applications/by-user/{uid} |
β | List<ApplicationDTO> |
200 OK |
POST | /api/applications/{id}/custom-fields |
Map<String, ?> |
β | 204 No Content |
POST | /api/applications/{id}/custom-fields/remove |
List<String> |
β | 204 No Content |
GET | /api/applications/{id}/custom-fields |
β | Map<String, ?> |
200 OK |
GET | /api/applications/by-ids |
List<Integer> |
List<ApplicationDTO> |
200 OK |
- POST
/api/applications
Creates a new application.
π₯ Request:
{
"code": "string",
"name": "string",
"description": "string",
"status": "ACTIVE",
"type": "EXTERNAL",
"owner": "string",
"picture": "string",
"url": "https://example.com/",
"slug": "string"
}
π€ Response:
{
"id": 1073741824,
"code": "string",
"name": "string",
"description": "string",
"status": "ACTIVE",
"type": "EXTERNAL",
"owner": "string",
"picture": "string",
"url": "https://example.com/",
"slug": "string",
"createdBy": "string",
"createdDate": "string",
"lastModifiedBy": "string",
"lastModifiedDate": "string"
}
- GET
/api/applications
- Query Params:
code
(optional): stringname
(optional): string
π€ Response:
[
{
"id": 1073741824,
"code": "string",
"name": "string",
"description": "string",
"status": "ACTIVE",
"type": "EXTERNAL",
"owner": "string",
"picture": "string",
"url": "https://example.com/",
"slug": "string",
"createdBy": "string",
"createdDate": "string",
"lastModifiedBy": "string",
"lastModifiedDate": "string"
}
]
- GET
/api/applications/{id}
π€ Response:
{
"id": 1073741824,
"code": "string",
"name": "string",
"description": "string",
"status": "ACTIVE",
"type": "EXTERNAL",
"owner": "string",
"picture": "string",
"url": "https://example.com/",
"slug": "string",
"createdBy": "string",
"createdDate": "string",
"lastModifiedBy": "string",
"lastModifiedDate": "string"
}
- PUT
/api/applications/{id}
π₯ Request:
{
"code": "string",
"name": "string",
"description": "string",
"status": "ACTIVE",
"type": "EXTERNAL",
"owner": "string",
"picture": "string",
"url": "https://example.com/",
"slug": "string"
}
π€ Response: (Same format as GET by ID)
- DELETE
/api/applications/{id}
π€ Response: 204 No Content
- GET
/api/applications/{id}/custom-fields
π€ Response:
{
"field1": "value1",
"field2": 69,
"field3": {
"field4": "value4"
}
}
- POST
/api/applications/{id}/custom-fields
π₯ Request:
{
"field1": "value1",
"field2": "value2"
}
π€ Response: 204 No Content
- POST
/api/applications/{id}/custom-fields/remove
π₯ Request:
["field1", "field2"]
π€ Response: 204 No Content
- POST
/api/applications/by-ids
π₯ Request:
[69, 99]
π€ Response:
[
{
"id": 69,
"code": "string",
"name": "string",
"description": "string",
"status": "ACTIVE"
},
{
"id": 99,
"code": "string",
"name": "string",
"description": "string",
"status": "ACTIVE"
}
]
- GET
/api/applications/by-user/{uid}
π€ Response:
[{
"id": 1073741824,
"code": "string",
"name": "string",
"description": "string",
"status": "ACTIVE",
"type": "EXTERNAL",
"owner": "string",
"picture": "string",
"url": "https://example.com/",
"slug": "string",
"createdBy": "string",
"createdDate": "string",
"lastModifiedBy": "string",
"lastModifiedDate": "string"
}]
- GET
/api/applications/denied-to-user/{uid}
π€ Response:
[{
"id": 1073741824,
"code": "string",
"name": "string",
"description": "string",
"status": "ACTIVE",
"type": "EXTERNAL",
"owner": "string",
"picture": "string",
"url": "https://example.com/",
"slug": "string",
"createdBy": "string",
"createdDate": "string",
"lastModifiedBy": "string",
"lastModifiedDate": "string"
}]
MΓ©todo | Endpoint | Request | Response | Status Code |
---|---|---|---|---|
POST | /api/departments |
DepartmentDTO |
DepartmentDTO |
201 Created |
GET | /api/departments |
β | List<DepartmentDTO> |
200 OK |
GET | /api/departments/{id} |
β | DepartmentDTO |
200 OK |
PUT | /api/departments/{id} |
DepartmentDTO |
DepartmentDTO |
200 OK |
DELETE | /api/departments/{id} |
β | β | 204 No Content |
GET | /api/departments/{id}/roles |
β | List<RoleDTO> |
200 OK |
POST | /api/departments/{id}/addRoles |
List<RoleDTO> |
List<RoleDTO> |
200 OK |
POST | /api/departments/{id}/removeRoles |
List<Integer> |
List<RoleDTO> |
200 OK |
POST | /api/departments/{id}/invite |
IGRPUserDTO |
β | 200 OK |
- POST
/api/departments
Creates a new departament.
π₯ Request:
{
"code": "TI",
"name": "Tecnologias de InformaΓ§Γ£o",
"description": "Departamento responsΓ‘vel pela infraestrutura tecnolΓ³gica",
"status": "ACTIVE",
"application_id": 1,
"parent_id": null
}
π€ Response:
{
"id": 3,
"code": "TI",
"name": "Tecnologias de InformaΓ§Γ£o",
"description": "Departamento responsΓ‘vel pela infraestrutura tecnolΓ³gica",
"status": "ACTIVE",
"application_id": 1,
"parent_id": null
}
- GET
/api/departments
List all departaments.
π€ Response:
[
{
"id": 1,
"code": "ADM",
"name": "AdministraΓ§Γ£o",
"description": "AdministraΓ§Γ£o Geral",
"status": "ACTIVE",
"application_id": 1,
"parent_id": null
}
]
- GET
/api/departments/{id}
Returns the details of a departament.
π€ Response:
{
"id": 1,
"code": "ADM",
"name": "AdministraΓ§Γ£o",
"description": "AdministraΓ§Γ£o Geral",
"status": "ACTIVE",
"application_id": 1,
"parent_id": null
}
- PUT
/api/departments/{id}
Updates a departament.
π₯ Request:
{
"code": "FIN",
"name": "Financeiro",
"description": "GestΓ£o de recursos financeiros",
"status": "INACTIVE",
"application_id": 1,
"parent_id": null
}
π€ Response: (Same format as GET by ID)
- DELETE
/api/departments/{id}
Removes a departament.
π€ Response: 204 No Content
- GET
/api/departments/{id}/roles
List all roles related to a departament.
π€ Response:
[
{
"id": 1,
"name": "Admin",
"description": "Acesso completo",
"departmentId": 1,
"parentId": null,
"status": "ACTIVE"
}
]
- POST
/api/departments/{id}/addRoles
Adds a list of roles to a departament.
π₯ Request:
[
{
"id": 2,
"name": "Editor",
"description": "Permite ediΓ§Γ£o de dados",
"departmentId": 1
}
]
π€ Response: List of RoleDTO
updated
- POST
/api/departments/{id}/removeRoles
Removes roles from departament.
π₯ Request:
[2, 3]
π€ Response: List of remaining RoleDTO
- POST
/api/departments/{id}/invite
Associates a new user to the department.
π₯ Request (IGRPUserDTO
):
{
"username": "mrodrigues",
"name": "Maria Rodrigues",
"email": "[email protected]",
"departmentId": 2,
"applicationId": 1
}
π€ Response: 200 OK
Method | Endpoint | Request | Response | Status Code |
---|---|---|---|---|
POST | /api/roles | RoleDTO | RoleDTO | 201 Created, 404 Not Found, 400 Bad Request |
GET | /api/roles | β | List<RoleDTO> | 200 OK |
GET | /api/roles/{id} | β | RoleDTO | 200 OK, 404 Not Found |
PUT | /api/roles/{id} | RoleDTO | RoleDTO | 200 OK, 404 Not Found |
DELETE | /api/roles/{id} | β | β | 204 No Content, 404 Not Found |
GET | /api/roles/{id}/permissions | β | List<PermissionDTO> | 200 OK, 404 Not Found |
POST | /api/roles/{id}/addPermissions | List<Integer> | List<PermissionDTO> | 200 OK, 404 Not Found |
POST | /api/roles/{id}/removePermissions | List<Integer> | List<PermissionDTO> | 200 OK, 404 Not Found |
- Permission
name
must be unique within the same Department. - Names are case-insensitive (e.g.,
role_delete_user
andROLE_DELETE_USER
are considered duplicates).
{
"id": 1073741824,
"name": "string",
"description": "string",
"departmentId": 1073741824,
"parentId": 1073741824,
"status": "ACTIVE"
}
- POST
/api/roles/:id
{
"id": 1073741824,
"name": "string",
"description": "string",
"departmentId": 1073741824,
"parentId": 1073741824,
"status": "ACTIVE"
}
[
{
"id": 355,
"name": "Parent",
"description": "Create Role Create Role",
"departmentId": 1,
"parentId": null,
"status": "ACTIVE"
},
{
"id": 356,
"name": "Create Child2",
"description": "Create Role Create Role",
"departmentId": 1,
"parentId": 355,
"status": "ACTIVE"
}
]
- GET
/api/roles/:id
{
"id": 204,
"name": "Role1: New Name",
"description": "Role1: New Name Description",
"departmentId": 1,
"parentId": null,
"status": "ACTIVE"
}
{
"status": "NOT_FOUND",
"title": "Get Role By Id",
"details": "Role with id: 2041 not found."
}
- POST
/api/roles/:id/permissions
[
{
"id": 4,
"name": "Create Resource Level 3",
"description": "Create Resource Level 3 - description",
"status": "ACTIVE",
"applicationId": 1
},
{
"id": 1,
"name": "Create Resource Level 1",
"description": "Create Resource Level 1 - description",
"status": "ACTIVE",
"applicationId": 1
},
{
"id": 2,
"name": "Create Resource Level 2",
"description": "Create Resource Level 2 - description",
"status": "ACTIVE",
"applicationId": 1
}
]
- POST
/api/roles/:id/addPermissions
[1,2,3,4]
[
{
"id": 2,
"name": "Create Resource Level 2",
"description": "Create Resource Level 2 - description",
"status": "ACTIVE",
"applicationId": 1
},
{
"id": 1,
"name": "Create Resource Level 1",
"description": "Create Resource Level 1 - description",
"status": "ACTIVE",
"applicationId": 1
},
{
"id": 4,
"name": "Create Resource Level 3",
"description": "Create Resource Level 3 - description",
"status": "ACTIVE",
"applicationId": 1
}
]
- POST
/api/roles/:id/removePermissions
[2, 4]
[
{
"id": 2,
"name": "Create Resource Level 2",
"description": "Create Resource Level 2 - description",
"status": "ACTIVE",
"applicationId": 1
},
{
"id": 4,
"name": "Create Resource Level 3",
"description": "Create Resource Level 3 - description",
"status": "ACTIVE",
"applicationId": 1
}
]
Method | Endpoint | Request | Response | Status Code |
---|---|---|---|---|
POST | /api/permissions | PermissionDTO | PermissionDTO | 201 Created, 404 Not Found |
GET | /api/permissions?applicationId={id} | β | List<PermissionDTO> | 200 OK |
GET | /api/permissions/{id} | β | PermissionDTO | 200 OK, 404 Not Found |
PUT | /api/permissions/{id} | PermissionDTO | PermissionDTO | 200 OK, 404 Not Found |
DELETE | /api/permissions/{id} | β | β | 204 No Content, 404 Not Found |
GET | /api/permissions/{id}/roles | β | List<RoleDTO> | 200 OK, 404 Not Found |
- Permission
name
must be unique within the same Application. - Names are case-insensitive (e.g.,
permission_create_user
andPERMISSION_CREATE_USER
are considered duplicates).
{
"id": 1073741824,
"name": "string",
"description": "string",
"status": "ACTIVE",
"applicationId": 1073741824
}
- POST
/api/permissions
{
"id": null,
"name": "string",
"description": "string",
"status": "ACTIVE",
"applicationId": 5
}
{
"status": "NOT_FOUND",
"title": "Create Permission",
"details": "Application with id: 5 not found."
}
MΓ©todo | Endpoint | Request | Response | Status Code |
---|---|---|---|---|
POST | /api/users/{id}/addRoles |
List<Integer> |
List<RoleDTO> |
201 Created |
POST | /api/users/{id}/removeRoles |
List<Integer> |
List<RoleDTO> |
200 OK |
GET | /api/users |
?applicationId={id}&departmentId={id}&name={name}&username={username}&email={email} |
List<UserDTO> |
200 OK |
GET | /api/users/{id}/roles |
?applicationId={id} |
List<RoleDTO> |
200 OK |
- GET
/api/users
Search Users applying mandatory filters.
π Required Parameters:
applicationId
departmentId
name
username
email
π€ Response:
[
{
"id": 5,
"username": "jfernandes",
"name": "JoΓ£o Fernandes",
"email": "[email protected]"
}
]
- POST
/api/users/{id}/addRoles
Associates new roles to a User.
π₯ Request:
[1, 3]
π€ Response:
[
{
"id": 1,
"name": "Admin",
"description": "Acesso completo",
"departmentId": 2,
"parentId": null,
"status": "ACTIVE"
}
]
- POST
/api/users/{id}/removeRoles
Remove roles from User.
π₯ Request:
[3]
π€ Response: List of remaining RoleDTO
- GET
/api/users/{id}/roles?applicationId={id}
Returns the roles associated with the User in the application context.
MΓ©todo | Endpoint | Request | Response | Status Code |
---|---|---|---|---|
POST | /api/menus |
MenuEntryDTO |
MenuEntryDTO |
201 Created |
GET | /api/menus |
β | List<MenuEntryDTO> |
200 OK |
GET | /api/menus/{id} |
β | MenuEntryDTO |
200 OK |
PUT | /api/menus/{id} |
MenuEntryDTO |
MenuEntryDTO |
200 OK |
DELETE | /api/menus/{id} |
β | β | 204 No Content |
- POST
/api/menus
π₯ Request:
{
"name": "string",
"type": "MENU_PAGE",
"position": 1073741824,
"icon": "string",
"status": "ACTIVE",
"target": "string",
"url": "string",
"parentId": null,
"applicationId": 1073741824,
"resourceId": 1073741824
}
π€ Response:
{
"id": 1073741824,
"name": "string",
"type": "MENU_PAGE",
"position": 1073741824,
"icon": "string",
"status": "ACTIVE",
"target": "string",
"url": "string",
"parentId": null,
"applicationId": 1073741824,
"resourceId": 1073741824,
"createdBy": "string",
"createdDate": "string",
"lastModifiedBy": "string",
"lastModifiedDate": "string"
}
- GET
/api/menus
- Query Params:
applicationId
(optional): stringname
(optional): stringtype
(optional): string
π€ Response:
[
{
"id": 1073741824,
"name": "string",
"type": "MENU_PAGE",
"position": 1073741824,
"icon": "string",
"status": "ACTIVE",
"target": "string",
"url": "string",
"parentId": 1073741824,
"applicationId": 1073741824,
"resourceId": 1073741824,
"createdBy": "string",
"createdDate": "string",
"lastModifiedBy": "string",
"lastModifiedDate": "string"
}
]
- GET
/api/menus/{id}
π€ Response:
{
"id": 1073741824,
"name": "string",
"type": "MENU_PAGE",
"position": 1073741824,
"icon": "string",
"status": "ACTIVE",
"target": "string",
"url": "string",
"parentId": 1073741824,
"applicationId": 1073741824,
"resourceId": 1073741824,
"createdBy": "string",
"createdDate": "string",
"lastModifiedBy": "string",
"lastModifiedDate": "string"
}
- PUT
/api/menus/{id}
π₯ Request:
{
"name": "string",
"type": "MENU_PAGE",
"position": 1073741824,
"icon": "string",
"status": "ACTIVE",
"target": "string",
"url": "string",
"parentId": null
}
π€ Response: (Same format as GET by ID)
- DELETE
/api/menus/{id}
π€ Response: 204 No Content
MΓ©todo | Endpoint | Request | Response | Status Code |
---|---|---|---|---|
POST | /api/resources |
ResourceDTO |
ResourceDTO |
201 Created |
GET | /api/resources |
β | List<ResourceDTO> |
200 OK |
GET | /api/resources/{id} |
β | ResourceDTO |
200 OK |
PUT | /api/resources/{id} |
ResourceDTO |
ResourceDTO |
200 OK |
DELETE | /api/resources/{id} |
β | β | 204 No Content |
POST | /api/resources/{id}/custom-fields |
Map<String, ?> |
β | 204 No Content |
POST | /api/resources/{id}/custom-fields/remove |
List<String> |
β | 204 No Content |
GET | /api/resources/{id}/custom-fields |
β | Map<String, ?> |
200 OK |
POST | /api/resources/{id}/add-items |
List<ResourceItemDTO> |
ResourceDTO |
200 OK |
POST | /api/resources/{id}/remove-items |
List<Integer> |
ResourceDTO |
200 OK |
- POST
/api/resources
π₯ Request:
{
"name": "string",
"type": "API",
"status": "ACTIVE",
"applicationId": 1073741824,
"items": [
{
"id": 1073741824,
"name": "string",
"url": "string",
"permissionId": 1073741824,
"resourceId": 1073741824
}
],
"externalId": "string"
}
π€ Response:
{
"id": 1073741824,
"name": "string",
"type": "API",
"status": "ACTIVE",
"applicationId": 1073741824,
"items": [
{
"id": 1073741824,
"name": "string",
"url": "string",
"permissionId": 1073741824,
"resourceId": 1073741824,
"createdBy": "string",
"createdDate": "string",
"lastModifiedBy": "string",
"lastModifiedDate": "string"
}
],
"externalId": "string",
"createdBy": "string",
"createdDate": "string",
"lastModifiedBy": "string",
"lastModifiedDate": "string"
}
- GET
/api/resources
- Query Params:
applicationId
(optional): stringname
(optional): stringtype
(optional): stringexternalID
(optional): string
π€ Response:
[
{
"id": 1073741824,
"name": "string",
"type": "API",
"status": "ACTIVE",
"applicationId": 1073741824,
"items": [
{
"id": 1073741824,
"name": "string",
"url": "string",
"permissionId": 1073741824,
"resourceId": 1073741824,
"createdBy": "string",
"createdDate": "string",
"lastModifiedBy": "string",
"lastModifiedDate": "string"
}
],
"externalId": "string",
"createdBy": "string",
"createdDate": "string",
"lastModifiedBy": "string",
"lastModifiedDate": "string"
}
]
- GET
/api/resources/{id}
π€ Response:
{
"id": 1073741824,
"name": "string",
"type": "API",
"status": "ACTIVE",
"applicationId": 1073741824,
"items": [
{
"id": 1073741824,
"name": "string",
"url": "string",
"permissionId": 1073741824,
"resourceId": 1073741824,
"createdBy": "string",
"createdDate": "string",
"lastModifiedBy": "string",
"lastModifiedDate": "string"
}
],
"externalId": "string",
"createdBy": "string",
"createdDate": "string",
"lastModifiedBy": "string",
"lastModifiedDate": "string"
}
- PUT
/api/resources/{id}
π₯ Request:
{
"name": "string",
"type": "API",
"status": "ACTIVE",
"applicationId": 1073741824,
"externalId": "string"
}
π€ Response: (Same format as GET by ID)
- DELETE
/api/resources/{id}
π€ Response: 204 No Content
- GET
/api/resources/{id}/custom-fields
π€ Response:
{
"field1": "value1",
"field2": 69,
"field3": {
"field4": "value4"
}
}
- POST
/api/resources/{id}/custom-fields
π₯ Request:
{
"field1": "value1",
"field2": "value2"
}
π€ Response: 204 No Content
- POST
/api/resources/{id}/custom-fields/remove
π₯ Request:
["field1", "field2"]
π€ Response: 204 No Content
- POST
/api/resources/{id}/add-items
π₯ Request:
[
{
"name": "string",
"url": "string",
"permissionId": 1073741824,
"resourceId": 1073741824
}
]
π€ Response:
{
"id": 1073741824,
"name": "string",
"type": "API",
"status": "ACTIVE",
"applicationId": 1073741824,
"items": [
{
"id": 1073741824,
"name": "string",
"url": "string",
"permissionId": 1073741824,
"resourceId": 1073741824,
"createdBy": "string",
"createdDate": "string",
"lastModifiedBy": "string",
"lastModifiedDate": "string"
}
],
"externalId": "string",
"createdBy": "string",
"createdDate": "string",
"lastModifiedBy": "string",
"lastModifiedDate": "string"
}
- POST
/api/resources/{id}/remove-items
π₯ Request:
[69, 99]
π€ Response:
{
"id": 1073741824,
"name": "string",
"type": "API",
"status": "ACTIVE",
"applicationId": 1073741824,
"items": [],
"externalId": "string",
"createdBy": "string",
"createdDate": "string",
"lastModifiedBy": "string",
"lastModifiedDate": "string"
}
This project supports integration with third-party IAM systems using the IAdapter
strategy:
- KeycloakAdapter: Handles interactions with Keycloak
- WSO2Adapter: Handles interactions with WSO2 Identity Server
To switch providers, update the application.properties
file:
app.auth.provider=keycloak
# or
app.auth.provider=wso2
The appropriate adapter will be injected automatically based on this configuration.
Profile-specific configuration can be managed via:
application-dev.properties
application-prod.properties
Supports:
- Database settings
- IAM provider configuration
- JWT settings
- Mail server config (optional)
# Run the Spring Boot app
mvn spring-boot:run
This project integrates the following tools to ensure code quality and maintainability:
Runs the tests and generates a coverage report:
# Run the following command
mvn clean verify
The coverage report will be available at:
target/site/jacoco/index.html
Generates the Javadoc API documentation:
# Run the following command
mvn javadoc:javadoc
The documentation can be found at:
target/reports/apidocs/index.html
The maven-javadoc-plugin is configured to attach a JAR with docs, also check:
target/access-management-*-javadoc.jar
Checks for known vulnerabilities in the dependencies:
# Using Maven verify phase
mvn verify
# Invoke directly
mvn dependency-check:check
The generated report will be available at:
target/reports/dependency-check-report.html
Contributions are welcome! Please open issues or submit pull requests with improvements or new features.
This project is licensed under the Apache 2.0 License. See the LICENSE file for details.