{"openapi":"3.0.3","info":{"version":"1.0.0","contact":{"name":"API Support","email":"support@contexthub.dev"},"title":"Context Hub - Auth Providers API","description":"User management and authentication provider system."},"servers":[{"url":"http://localhost:3000","description":"Development Server"}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key"},"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}},"schemas":{"AuthProvider":{"type":"object","required":["name","issuerUrl"],"properties":{"id":{"type":"string","format":"uuid","description":"Unique identifier","readOnly":true},"name":{"type":"string","description":"Unique name for the auth provider","example":"keycloak-prod"},"displayName":{"type":"string","description":"Human-readable name","example":"Keycloak Production"},"issuerUrl":{"type":"string","format":"uri","description":"The issuer URL (iss claim value in JWTs)","example":"https://auth.example.com/realms/master"},"jwksUrl":{"type":"string","format":"uri","description":"URL to the JWKS endpoint for key retrieval","example":"https://auth.example.com/realms/master/protocol/openid-connect/certs"},"publicKeys":{"type":"array","description":"Optional public keys for offline verification (JWK format)","items":{"type":"object","properties":{"kid":{"type":"string","description":"Key ID"},"kty":{"type":"string","description":"Key type (RSA, EC, etc.)"},"n":{"type":"string","description":"Modulus (for RSA keys)"},"e":{"type":"string","description":"Exponent (for RSA keys)"}}}},"clientId":{"type":"string","description":"Client ID for this service","example":"api-service"},"tokenEndpoint":{"type":"string","format":"uri","description":"Token endpoint for authentication","example":"https://auth.example.com/realms/master/protocol/openid-connect/token"},"metadata":{"type":"object","description":"Additional provider-specific metadata"},"isActive":{"type":"boolean","description":"Whether this provider is active","default":true},"createdAt":{"type":"string","format":"date-time","description":"Creation timestamp","readOnly":true},"updatedAt":{"type":"string","format":"date-time","description":"Last update timestamp","readOnly":true}}},"AuthProviderList":{"type":"object","properties":{"providers":{"type":"array","items":{"$ref":"#/components/schemas/AuthProvider"}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}}}}},"OidcConfiguration":{"type":"object","properties":{"issuerUrl":{"type":"string","format":"uri"},"jwksUrl":{"type":"string","format":"uri"},"tokenEndpoint":{"type":"string","format":"uri"},"authorizationEndpoint":{"type":"string","format":"uri"},"userinfoEndpoint":{"type":"string","format":"uri"},"endSessionEndpoint":{"type":"string","format":"uri"},"supportedScopes":{"type":"array","items":{"type":"string"}},"supportedResponseTypes":{"type":"array","items":{"type":"string"}},"metadata":{"type":"object","description":"Full configuration object"}}},"PublicKey":{"type":"object","required":["kid","kty"],"properties":{"kid":{"type":"string","description":"Key ID","example":"key-1"},"kty":{"type":"string","description":"Key type","example":"RSA"},"alg":{"type":"string","description":"Algorithm","example":"RS256"},"use":{"type":"string","description":"Key usage","example":"sig"},"n":{"type":"string","description":"Modulus (for RSA keys)"},"e":{"type":"string","description":"Exponent (for RSA keys)"},"crv":{"type":"string","description":"Curve (for EC keys)"},"x":{"type":"string","description":"X coordinate (for EC keys)"},"y":{"type":"string","description":"Y coordinate (for EC keys)"}}}}},"paths":{"/api/v1/auth-providers":{"get":{"summary":"List all auth providers","tags":["Auth Providers"],"security":[{"ApiKeyAuth":[]}],"description":"Get a list of all authentication providers with optional filtering.\n**Required Permission: READ**\n","parameters":[{"in":"query","name":"name","schema":{"type":"string"},"description":"Filter by name"},{"in":"query","name":"isActive","schema":{"type":"boolean"},"description":"Filter by active status"},{"in":"query","name":"search","schema":{"type":"string"},"description":"Search in name, display name, or issuer URL"},{"in":"query","name":"page","schema":{"type":"integer","minimum":1,"default":1},"description":"Page number"},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":10},"description":"Items per page"},{"in":"query","name":"orderBy","schema":{"type":"string","enum":["name","createdAt","updatedAt"],"default":"name"},"description":"Field to order by"},{"in":"query","name":"orderDirection","schema":{"type":"string","enum":["asc","desc"],"default":"asc"},"description":"Order direction"}],"responses":{"200":{"description":"List of auth providers","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthProviderList"}}}},"400":{"description":"Invalid query parameters"},"403":{"$ref":"#/components/responses/PermissionDenied"}}},"post":{"summary":"Create a new auth provider","tags":["Auth Providers"],"security":[{"ApiKeyAuth":[]}],"description":"Create a new authentication provider.\n**Required Permission: CREATE**\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthProvider"}}}},"responses":{"201":{"description":"Auth provider created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"provider":{"$ref":"#/components/schemas/AuthProvider"}}}}}},"400":{"description":"Invalid request data"},"403":{"$ref":"#/components/responses/PermissionDenied"},"409":{"description":"Auth provider with the same name already exists"}}}},"/api/v1/auth-providers/{id}":{"get":{"summary":"Get auth provider by ID","tags":["Auth Providers"],"security":[{"ApiKeyAuth":[]}],"description":"Get a single authentication provider by its ID.\n**Required Permission: READ**\n","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Auth provider ID"}],"responses":{"200":{"description":"Auth provider details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthProvider"}}}},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"description":"Auth provider not found"}}},"put":{"summary":"Update an auth provider","tags":["Auth Providers"],"security":[{"ApiKeyAuth":[]}],"description":"Update an existing authentication provider.\n**Required Permission: UPDATE**\n","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Auth provider ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"displayName":{"type":"string"},"issuerUrl":{"type":"string","format":"uri"},"jwksUrl":{"type":"string","format":"uri"},"publicKeys":{"type":"array","items":{"$ref":"#/components/schemas/PublicKey"}},"clientId":{"type":"string"},"tokenEndpoint":{"type":"string","format":"uri"},"metadata":{"type":"object"},"isActive":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Auth provider updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"provider":{"$ref":"#/components/schemas/AuthProvider"}}}}}},"400":{"description":"Invalid request data"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"description":"Auth provider not found"},"409":{"description":"Auth provider with the same name already exists"}}},"delete":{"summary":"Delete an auth provider","tags":["Auth Providers"],"security":[{"ApiKeyAuth":[]}],"description":"Delete an authentication provider. This will fail if the provider has associated user identities.\n**Required Permission: DELETE**\n","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Auth provider ID"}],"responses":{"200":{"description":"Auth provider deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"description":"Auth provider not found"},"409":{"description":"Cannot delete provider with associated user identities"}}}},"/api/v1/auth-providers/discover":{"post":{"summary":"Discover OIDC configuration","tags":["Auth Providers"],"security":[{"ApiKeyAuth":[]}],"description":"Discover OpenID Connect configuration from an issuer URL.\n**Required Permission: READ**\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["issuerUrl"],"properties":{"issuerUrl":{"type":"string","format":"uri","description":"OIDC issuer URL","example":"https://auth.example.com/realms/master"}}}}}},"responses":{"200":{"description":"OIDC configuration discovered successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"configuration":{"$ref":"#/components/schemas/OidcConfiguration"}}}}}},"400":{"description":"Invalid issuer URL or discovery failed"},"403":{"$ref":"#/components/responses/PermissionDenied"}}}},"/api/v1/auth-providers/{id}/keys":{"put":{"summary":"Update public keys","tags":["Auth Providers"],"security":[{"ApiKeyAuth":[]}],"description":"Update or add public keys for offline JWT verification.\n**Required Permission: UPDATE**\n","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Auth provider ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["keys"],"properties":{"keys":{"type":"array","items":{"$ref":"#/components/schemas/PublicKey"}}}}}}},"responses":{"200":{"description":"Public keys updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"provider":{"$ref":"#/components/schemas/AuthProvider"}}}}}},"400":{"description":"Invalid request data"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"description":"Auth provider not found"}}}},"/api/v1/auth-providers/{id}/jwks":{"get":{"summary":"Fetch JWKS from provider","tags":["Auth Providers"],"security":[{"ApiKeyAuth":[]}],"description":"Fetch the current JWKS from the provider's jwksUrl.\n**Required Permission: READ**\n","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Auth provider ID"}],"responses":{"200":{"description":"JWKS fetched successfully","content":{"application/json":{"schema":{"type":"object","properties":{"jwks":{"type":"object","properties":{"keys":{"type":"array","items":{"$ref":"#/components/schemas/PublicKey"}}}},"provider":{"$ref":"#/components/schemas/AuthProvider"}}}}}},"400":{"description":"Provider does not have a JWKS URL"},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"description":"Auth provider not found"},"502":{"description":"Failed to fetch JWKS from provider"}}}},"/api/v1/auth-providers/{id}/stats":{"get":{"summary":"Get auth provider statistics","tags":["Auth Providers"],"security":[{"ApiKeyAuth":[]}],"description":"Get statistics for an auth provider, including usage counts.\n**Required Permission: READ**\n","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string","format":"uuid"},"description":"Auth provider ID"}],"responses":{"200":{"description":"Statistics retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"provider":{"$ref":"#/components/schemas/AuthProvider"},"stats":{"type":"object","properties":{"identityCount":{"type":"integer","description":"Number of user identities with this provider"},"userCount":{"type":"integer","description":"Number of unique users with this provider"},"auditCount":{"type":"integer","description":"Number of JWT verification audit entries"},"successfulVerifications":{"type":"integer","description":"Number of successful JWT verifications"},"failedVerifications":{"type":"integer","description":"Number of failed JWT verifications"},"verificationSuccessRate":{"type":"string","description":"Success rate percentage"},"recentJwtAudits":{"type":"array","description":"Recent JWT verification audits","items":{"type":"object"}}}}}}}}},"403":{"$ref":"#/components/responses/PermissionDenied"},"404":{"description":"Auth provider not found"}}}},"/api/v1/auth-providers/jwt/verify":{"post":{"summary":"Verify a JWT token","tags":["JWT"],"security":[{"ApiKeyAuth":[]}],"description":"Verifies a JWT token against the configured auth providers.\nReturns information about the token and its claims if valid.\n**Required Permission: READ**\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string","description":"The JWT token to verify"},"audience":{"type":"string","description":"Optional audience to verify against"}}}}}},"responses":{"200":{"description":"Token verified successfully","content":{"application/json":{"schema":{"type":"object","properties":{"valid":{"type":"boolean","description":"Whether the token is valid"},"payload":{"type":"object","description":"The token payload"},"provider":{"type":"object","description":"Information about the auth provider"},"user":{"type":"object","description":"User information if the subject is found"}}}}}},"400":{"description":"Invalid token format or missing token"},"401":{"description":"Token verification failed"},"403":{"description":"Invalid API key or insufficient permissions"}}}},"/api/v1/auth-providers/jwt/decode":{"post":{"summary":"Decode a JWT token without verification","tags":["JWT"],"security":[{"ApiKeyAuth":[]}],"description":"Decodes a JWT token without verifying its signature.\nThis endpoint only parses the token and returns its contents.\n**Required Permission: READ**\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string","description":"The JWT token to decode"}}}}}},"responses":{"200":{"description":"Token decoded successfully","content":{"application/json":{"schema":{"type":"object","properties":{"header":{"type":"object","description":"The token header"},"payload":{"type":"object","description":"The token payload"}}}}}},"400":{"description":"Invalid token format or missing token"},"403":{"description":"Invalid API key or insufficient permissions"}}}},"/api/v1/auth-providers/jwt/whoami":{"get":{"summary":"Get current user information from JWT token","tags":["JWT"],"security":[{"BearerAuth":[]}],"description":"Returns information about the authenticated user based on the JWT token.\nThis endpoint requires JWT authentication.\n","responses":{"200":{"description":"User information retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"username":{"type":"string"},"role":{"type":"string"}}},"token":{"type":"object","description":"Summary of the token claims"},"identities":{"type":"array","description":"Auth provider identities for this user"}}}}}},"401":{"description":"JWT authentication required"}}}},"/api/v1/auth-providers/jwt/test-auth":{"get":{"summary":"Test endpoint supporting both JWT and API key auth","tags":["JWT"],"security":[{"ApiKeyAuth":[]},{"BearerAuth":[]}],"description":"This endpoint can be accessed with either JWT token or API key.\nIt returns information about how the authentication was performed.\n","responses":{"200":{"description":"Authentication successful","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"authMethod":{"type":"string","enum":["jwt","apiKey","both"]},"authInfo":{"type":"object"}}}}}},"401":{"description":"Authentication required"},"403":{"description":"Invalid credentials or insufficient permissions"}}}}},"tags":[{"name":"Auth Providers","description":"Management of authentication providers"},{"name":"JWT","description":"JWT token verification and testing endpoints"}]}