Files
oauth/storage/api-docs/api-docs.json
Josep Piguillem c2b5291a74 Initial commit: OAuth IAM Laravel application
Laravel-based OAuth/IAM service with Passport, Vue 3 frontend, and
Docker Compose setup for local and production deployment.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 01:02:41 +02:00

1133 lines
40 KiB
JSON

{
"openapi": "3.0.0",
"info": {
"title": "OAuth2 Identity Server API",
"description": "Servidor de identidad/OAuth2 (Laravel Passport) para que aplicaciones de terceros se autentiquen y gestionen usuarios. Pensada para ser consumida por aplicaciones cliente de terceros (Angular, Flutter, NestJS, etc.) que quieran construir su propio panel sin depender de la sesión de Laravel.",
"version": "1.0.0"
},
"servers": [
{
"url": "/api",
"description": "API base URL"
}
],
"paths": {
"/analytics/summary": {
"get": {
"tags": [
"Analytics"
],
"summary": "Métricas de uso: logins por día, por app, usuarios más activos y actividad reciente",
"description": "Requiere el permiso users.view (o un token client_credentials, que actúa como servicio de confianza).",
"operationId": "b34ca6a4b161498d5b34ed3054ddc39d",
"parameters": [
{
"name": "days",
"in": "query",
"description": "Ventana en días (7-90, default 30)",
"required": false,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"description": "Resumen de analíticas"
},
"403": {
"description": "Sin permiso users.view"
}
},
"security": [
{
"oauth2": [
"users:read"
]
}
]
}
},
"/apps": {
"get": {
"tags": [
"Users"
],
"summary": "Listar todas las apps (clientes OAuth) registradas en el sistema",
"description": "Requiere el permiso users.view (o un token client_credentials, que actúa como servicio de confianza). Se usa para armar el selector de \"roles por app\".",
"operationId": "5a879a1d739e5b67999e22de46d3223b",
"responses": {
"200": {
"description": "Listado de apps"
},
"403": {
"description": "Sin permiso users.view"
}
},
"security": [
{
"oauth2": [
"users:read"
]
}
]
}
},
"/authorized-apps": {
"get": {
"tags": [
"Account"
],
"summary": "Listar apps de terceros a las que le diste acceso a tu cuenta",
"operationId": "52cd9fb5a0e5a127774bdd7fa8456851",
"responses": {
"200": {
"description": "Listado de tokens/apps autorizadas"
}
},
"security": [
{
"oauth2": [
"account:read"
]
}
]
}
},
"/authorized-apps/{tokenId}": {
"delete": {
"tags": [
"Account"
],
"summary": "Revocar el acceso de una app de terceros",
"operationId": "59b2351fe30ac2a4c717926d094d08c9",
"parameters": [
{
"name": "tokenId",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"204": {
"description": "Acceso revocado"
},
"404": {
"description": "No existe o no es tuyo"
}
},
"security": [
{
"oauth2": [
"account:write"
]
}
]
}
},
"/clients": {
"get": {
"tags": [
"Account"
],
"summary": "Listar tus clientes OAuth (apps que registraste)",
"operationId": "6536f8d22d25758c3e14dbbe8e228af0",
"responses": {
"200": {
"description": "Listado de clientes",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Client"
}
}
}
}
},
"422": {
"description": "El token no tiene un usuario asociado (ej. client_credentials)"
}
},
"security": [
{
"oauth2": [
"account:read"
]
}
]
},
"post": {
"tags": [
"Account"
],
"summary": "Registrar un nuevo cliente OAuth (tu app)",
"operationId": "74a35b85418e09c2489915865dd22445",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"required": [
"name",
"grant_type"
],
"properties": {
"name": {
"type": "string"
},
"grant_type": {
"type": "string",
"enum": [
"authorization_code",
"client_credentials",
"password"
]
},
"redirect_uris": {
"type": "array",
"items": {
"type": "string"
}
},
"confidential": {
"type": "boolean",
"default": true
}
},
"type": "object"
}
}
}
},
"responses": {
"201": {
"description": "Cliente creado (incluye plain_secret una sola vez)"
},
"422": {
"description": "Datos inválidos o token sin usuario asociado"
}
},
"security": [
{
"oauth2": [
"account:write"
]
}
]
}
},
"/clients/{client}": {
"put": {
"tags": [
"Account"
],
"summary": "Editar uno de tus clientes OAuth",
"operationId": "01a0e98b651c8cda71034d93d40b8b27",
"parameters": [
{
"name": "client",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Cliente actualizado",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Client"
}
}
}
},
"404": {
"description": "No es tuyo o no existe"
}
},
"security": [
{
"oauth2": [
"account:write"
]
}
]
},
"delete": {
"tags": [
"Account"
],
"summary": "Revocar uno de tus clientes OAuth (y sus tokens)",
"operationId": "ed21785e71ab67958cf6216b6cf263a3",
"parameters": [
{
"name": "client",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"204": {
"description": "Revocado"
},
"404": {
"description": "No es tuyo o no existe"
}
},
"security": [
{
"oauth2": [
"account:write"
]
}
]
}
},
"/personal-access-tokens": {
"get": {
"tags": [
"Account"
],
"summary": "Listar tus Personal Access Tokens",
"operationId": "b94780059af9e6c94456302b3142b3cb",
"responses": {
"200": {
"description": "Listado de tokens"
}
},
"security": [
{
"oauth2": [
"account:read"
]
}
]
},
"post": {
"tags": [
"Account"
],
"summary": "Crear un Personal Access Token (tipo API key)",
"operationId": "6e653bdc7fa6bdd2768842f92d575ae7",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"required": [
"name"
],
"properties": {
"name": {
"type": "string"
},
"scopes": {
"type": "array",
"items": {
"type": "string"
}
}
},
"type": "object"
}
}
}
},
"responses": {
"201": {
"description": "Token creado (access_token solo se muestra esta vez)"
}
},
"security": [
{
"oauth2": [
"account:write"
]
}
]
}
},
"/personal-access-tokens/{tokenId}": {
"delete": {
"tags": [
"Account"
],
"summary": "Revocar un Personal Access Token",
"operationId": "d72271ccb6b2630a6d33c20516229723",
"parameters": [
{
"name": "tokenId",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"204": {
"description": "Revocado"
},
"404": {
"description": "No existe o no es tuyo"
}
},
"security": [
{
"oauth2": [
"account:write"
]
}
]
}
},
"/user": {
"get": {
"tags": [
"Users"
],
"summary": "Usuario del token actual (whoami) + sus roles global y en la app que llama",
"operationId": "853204b4b2f8a255a3721aaca3407e72",
"responses": {
"200": {
"description": "Usuario autenticado",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
},
"401": {
"description": "Token inválido o sin usuario asociado (ej. client_credentials)"
}
},
"security": [
{
"oauth2": []
}
]
}
},
"/users": {
"get": {
"tags": [
"Users"
],
"summary": "Listar usuarios",
"description": "Incluye usuarios pendientes de aprobación del panel admin (ver campo approved_at) — esa aprobación solo gobierna el acceso al panel de sesión de esta app, no la consulta de usuarios vía API.",
"operationId": "7208c29037df2b8bb02499ba39ed8a78",
"responses": {
"200": {
"description": "Listado de usuarios",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/User"
}
}
}
}
},
"403": {
"description": "Sin permiso users.view"
}
},
"security": [
{
"oauth2": [
"users:read"
]
}
]
},
"post": {
"tags": [
"Users"
],
"summary": "Crear un usuario",
"operationId": "262eb5ca1fdea354023c0a8870442c1e",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"required": [
"name",
"email",
"password"
],
"properties": {
"name": {
"type": "string"
},
"email": {
"type": "string",
"format": "email"
},
"password": {
"type": "string",
"format": "password"
},
"role": {
"type": "string",
"example": "user"
}
},
"type": "object"
}
}
}
},
"responses": {
"201": {
"description": "Usuario creado",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
},
"403": {
"description": "Sin permiso users.create"
}
},
"security": [
{
"oauth2": [
"users:write"
]
}
]
}
},
"/users/{user}": {
"get": {
"tags": [
"Users"
],
"summary": "Ver un usuario (el propio siempre permitido; otros requieren users.view)",
"operationId": "a8a7a1f979a2abb839b4b320238106fc",
"parameters": [
{
"name": "user",
"in": "path",
"required": true,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"description": "Datos del usuario",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
},
"403": {
"description": "Sin permiso users.view"
}
},
"security": [
{
"oauth2": [
"users:read"
]
}
]
},
"put": {
"tags": [
"Users"
],
"summary": "Editar un usuario (el propio siempre permitido; rol/estado y otros usuarios requieren users.update)",
"operationId": "4ac3faef1359369686fdd433daad2bee",
"parameters": [
{
"name": "user",
"in": "path",
"required": true,
"schema": {
"type": "integer"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"properties": {
"name": {
"type": "string"
},
"email": {
"type": "string",
"format": "email"
},
"password": {
"type": "string",
"format": "password"
},
"is_active": {
"type": "boolean"
},
"role": {
"type": "string"
}
},
"type": "object"
}
}
}
},
"responses": {
"200": {
"description": "Usuario actualizado",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
},
"403": {
"description": "Sin permiso users.update"
}
},
"security": [
{
"oauth2": [
"users:write"
]
}
]
},
"delete": {
"tags": [
"Users"
],
"summary": "Borrar un usuario (requiere users.delete; no se puede autoeliminar)",
"operationId": "371ba09bb6d4a95792dd93040f8812b3",
"parameters": [
{
"name": "user",
"in": "path",
"required": true,
"schema": {
"type": "integer"
}
}
],
"responses": {
"204": {
"description": "Usuario borrado"
},
"403": {
"description": "Sin permiso users.delete"
},
"422": {
"description": "No se puede autoeliminar ni borrar al último admin"
}
},
"security": [
{
"oauth2": [
"users:write"
]
}
]
}
},
"/users/trashed": {
"get": {
"tags": [
"Users"
],
"summary": "Listar usuarios borrados (papelera)",
"operationId": "ac10f52342c5e5c0d77d46764b6e0637",
"responses": {
"200": {
"description": "Listado de usuarios en la papelera",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/User"
}
}
}
}
},
"403": {
"description": "Sin permiso users.view"
}
},
"security": [
{
"oauth2": [
"users:read"
]
}
]
}
},
"/users/{id}/restore": {
"post": {
"tags": [
"Users"
],
"summary": "Restaurar un usuario borrado",
"operationId": "0ec16b4b1d92c2d61463d74d9c045701",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"description": "Usuario restaurado",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
},
"403": {
"description": "Sin permiso users.update"
}
},
"security": [
{
"oauth2": [
"users:write"
]
}
]
}
},
"/users/{id}/force": {
"delete": {
"tags": [
"Users"
],
"summary": "Borrar un usuario definitivamente (tiene que estar en la papelera)",
"operationId": "093b171b76c7e960668a7c9adf16e9ef",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "integer"
}
}
],
"responses": {
"204": {
"description": "Borrado definitivamente"
},
"403": {
"description": "Sin permiso users.delete"
}
},
"security": [
{
"oauth2": [
"users:write"
]
}
]
}
},
"/users/pending": {
"get": {
"tags": [
"Users"
],
"summary": "Listar usuarios autorregistrados que todavía no aprobó ningún admin",
"operationId": "373548f0068d0e9154443cb895254faf",
"responses": {
"200": {
"description": "Listado de usuarios pendientes",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/User"
}
}
}
}
},
"403": {
"description": "Sin permiso users.view"
}
},
"security": [
{
"oauth2": [
"users:read"
]
}
]
}
},
"/users/{user}/approve": {
"post": {
"tags": [
"Users"
],
"summary": "Aprobar un registro pendiente",
"operationId": "c9f59dde1d9a997c3f33c22af5ffc0f0",
"parameters": [
{
"name": "user",
"in": "path",
"required": true,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"description": "Usuario aprobado",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
},
"403": {
"description": "Sin permiso users.update"
}
},
"security": [
{
"oauth2": [
"users:write"
]
}
]
}
},
"/users/{user}/app-roles": {
"get": {
"tags": [
"Users"
],
"summary": "Roles que el usuario tiene en cada app (el propio siempre permitido; otros requieren users.view)",
"operationId": "9f0336429727034d7b79d1dd1ec210e2",
"parameters": [
{
"name": "user",
"in": "path",
"required": true,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"description": "Roles agrupados por app"
}
},
"security": [
{
"oauth2": [
"users:read"
]
}
]
},
"post": {
"tags": [
"Users"
],
"summary": "Asignar un rol a un usuario dentro de una app (requiere users.update; sin bypass por self)",
"operationId": "108e24d381e03dcbde787f187bff167f",
"parameters": [
{
"name": "user",
"in": "path",
"required": true,
"schema": {
"type": "integer"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"required": [
"client_id",
"role"
],
"properties": {
"client_id": {
"type": "string",
"format": "uuid"
},
"role": {
"type": "string",
"example": "admin"
}
},
"type": "object"
}
}
}
},
"responses": {
"201": {
"description": "Rol asignado"
},
"403": {
"description": "Sin permiso users.update"
}
},
"security": [
{
"oauth2": [
"users:write"
]
}
]
}
},
"/users/{user}/app-roles/{clientId}/{role}": {
"delete": {
"tags": [
"Users"
],
"summary": "Quitarle a un usuario un rol dentro de una app (requiere users.update)",
"operationId": "60321b766e2a52bc435d7c93ed35a6dc",
"parameters": [
{
"name": "user",
"in": "path",
"required": true,
"schema": {
"type": "integer"
}
},
{
"name": "clientId",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "role",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"204": {
"description": "Rol quitado"
},
"403": {
"description": "Sin permiso users.update"
}
},
"security": [
{
"oauth2": [
"users:write"
]
}
]
}
}
},
"components": {
"schemas": {
"Client": {
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string",
"example": "Mi app Angular"
},
"grant_types": {
"type": "array",
"items": {
"type": "string"
},
"example": [
"authorization_code",
"refresh_token"
]
},
"redirect_uris": {
"type": "array",
"items": {
"type": "string"
},
"example": [
"https://mi-app.com/callback"
]
},
"revoked": {
"type": "boolean"
}
},
"type": "object"
},
"User": {
"properties": {
"id": {
"type": "integer",
"example": 1
},
"name": {
"type": "string",
"example": "Ada Lovelace"
},
"email": {
"type": "string",
"format": "email",
"example": "ada@example.com"
},
"is_active": {
"type": "boolean",
"example": true
},
"roles": {
"type": "array",
"items": {
"type": "string"
},
"example": [
"user"
]
},
"app_roles": {
"description": "Roles del usuario específicos de la app que llama (el client_id del token usado).",
"type": "array",
"items": {
"type": "string"
},
"example": [
"editor"
]
},
"created_at": {
"type": "string",
"format": "date-time"
},
"deleted_at": {
"description": "Solo presente para usuarios en la papelera (soft-deleted).",
"type": "string",
"format": "date-time",
"nullable": true
},
"approved_at": {
"description": "Null = todavía no lo aprobó ningún admin (registro pendiente).",
"type": "string",
"format": "date-time",
"nullable": true
}
},
"type": "object"
}
},
"securitySchemes": {
"oauth2": {
"type": "oauth2",
"description": "Servidor de autorización OAuth2 (Laravel Passport). Soporta Authorization Code + PKCE, Client Credentials y Password Grant.",
"flows": {
"authorizationCode": {
"authorizationUrl": "/oauth/authorize",
"tokenUrl": "/oauth/token",
"refreshUrl": "/oauth/token",
"scopes": {
"users:read": "Leer usuarios",
"users:write": "Crear, editar y borrar usuarios",
"account:read": "Leer tus clientes OAuth, tokens y apps autorizadas",
"account:write": "Gestionar tus clientes OAuth, tokens y apps autorizadas"
}
},
"clientCredentials": {
"tokenUrl": "/oauth/token",
"scopes": {
"users:read": "Leer usuarios",
"users:write": "Crear, editar y borrar usuarios",
"account:read": "Leer tus clientes OAuth, tokens y apps autorizadas",
"account:write": "Gestionar tus clientes OAuth, tokens y apps autorizadas"
}
},
"password": {
"tokenUrl": "/oauth/token",
"scopes": {
"users:read": "Leer usuarios",
"users:write": "Crear, editar y borrar usuarios",
"account:read": "Leer tus clientes OAuth, tokens y apps autorizadas",
"account:write": "Gestionar tus clientes OAuth, tokens y apps autorizadas"
}
}
}
}
}
},
"tags": [
{
"name": "Analytics",
"description": "Analytics"
},
{
"name": "Users",
"description": "Users"
},
{
"name": "Account",
"description": "Account"
}
]
}