Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
234 changes: 230 additions & 4 deletions app/Http/Controllers/OAuth2/OAuth2ProviderController.php

Large diffs are not rendered by default.

176 changes: 176 additions & 0 deletions app/Swagger/OAuth2ProviderControllerSchemas.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
<?php

namespace App\Swagger\schemas;

use OpenApi\Attributes as OA;

#[OA\Schema(
Comment thread
matiasperrone-exo marked this conversation as resolved.
schema: 'OAuth2TokenResponse',
title: 'OAuth2 Token Response',
description: 'Successful token response per RFC 6749 §5.1',
type: 'object',
required: ['access_token', 'token_type'],
properties: [
new OA\Property(property: 'access_token', type: 'string', description: 'The access token issued by the authorization server'),
new OA\Property(property: 'token_type', type: 'string', description: 'The type of the token (typically Bearer)', example: 'Bearer'),
new OA\Property(property: 'expires_in', type: 'integer', description: 'Lifetime of the access token in seconds', example: 3600),
new OA\Property(property: 'refresh_token', type: 'string', description: 'Refresh token (only if access_type=offline)', nullable: true),
new OA\Property(property: 'scope', type: 'string', description: 'Space-delimited list of granted scopes'),
new OA\Property(property: 'id_token', type: 'string', description: 'ID token JWT (only for OpenID Connect flows with openid scope)', nullable: true),
]
)]
class OAuth2TokenResponseSchema
{
}

#[OA\Schema(
schema: 'OAuth2ErrorResponse',
title: 'OAuth2 Error Response',
description: 'Error response per RFC 6749 §5.2',
type: 'object',
required: ['error'],
properties: [
new OA\Property(property: 'error', type: 'string', description: 'Error code', example: 'invalid_request'),
new OA\Property(property: 'error_description', type: 'string', description: 'Human-readable error description'),
]
)]
class OAuth2ErrorResponseSchema
{
}

#[OA\Schema(
Comment thread
matiasperrone-exo marked this conversation as resolved.
schema: 'OAuth2IntrospectionResponse',
title: 'OAuth2 Token Introspection Response',
description: 'Token introspection response per RFC 7662',
type: 'object',
required: ['active'],
properties: [
new OA\Property(property: 'active', type: 'boolean', description: 'Whether the token is active'),
new OA\Property(property: 'access_token', type: 'string', description: 'The access token value'),
new OA\Property(property: 'client_id', type: 'string', description: 'Client identifier'),
new OA\Property(property: 'application_type', type: 'string', description: 'Client application type', enum: ['WEB', 'NATIVE', 'JS']),
new OA\Property(property: 'token_type', type: 'string', description: 'Token type', example: 'Bearer'),
new OA\Property(property: 'scope', type: 'string', description: 'Space-delimited scopes'),
new OA\Property(property: 'audience', type: 'string', description: 'Token audience'),
new OA\Property(property: 'expires_in', type: 'integer', description: 'Remaining lifetime in seconds'),
new OA\Property(property: 'user_id', type: 'integer', description: 'Resource owner user ID', nullable: true),
new OA\Property(property: 'user_identifier', type: 'string', description: 'Resource owner identifier', nullable: true),
new OA\Property(property: 'user_email', type: 'string', description: 'Resource owner email', nullable: true),
new OA\Property(property: 'user_first_name', type: 'string', description: 'Resource owner first name', nullable: true),
new OA\Property(property: 'user_last_name', type: 'string', description: 'Resource owner last name', nullable: true),
new OA\Property(property: 'user_pic', type: 'string', format: 'uri', description: 'Resource owner profile picture URL', nullable: true),
new OA\Property(
property: 'user_groups',
type: 'array',
description: 'Resource owner group memberships',
items: new OA\Items(
type: 'object',
properties: [
new OA\Property(property: 'id', type: 'integer'),
new OA\Property(property: 'title', type: 'string'),
new OA\Property(property: 'description', type: 'string'),
]
),
nullable: true
),
new OA\Property(property: 'user_email_verified', type: 'boolean', description: 'Whether the user email is verified', nullable: true),
new OA\Property(property: 'user_language', type: 'string', description: 'User preferred language', nullable: true),
new OA\Property(property: 'user_country', type: 'string', description: 'User country', nullable: true),
new OA\Property(property: 'allowed_return_uris', type: 'string', description: 'Space-delimited allowed return URIs'),
new OA\Property(property: 'allowed_origins', type: 'string', description: 'Space-delimited allowed origins'),
]
)]
class OAuth2IntrospectionResponseSchema
{
}

#[OA\Schema(
Comment thread
matiasperrone-exo marked this conversation as resolved.
schema: 'JWKSResponse',
title: 'JSON Web Key Set',
description: 'JWK Set document per RFC 7517',
type: 'object',
required: ['keys'],
properties: [
new OA\Property(
property: 'keys',
type: 'array',
description: 'Array of JSON Web Keys',
items: new OA\Items(
type: 'object',
properties: [
new OA\Property(property: 'kty', type: 'string', description: 'Key type', example: 'RSA'),
new OA\Property(property: 'kid', type: 'string', description: 'Key ID'),
new OA\Property(property: 'use', type: 'string', description: 'Key usage', example: 'sig'),
new OA\Property(property: 'alg', type: 'string', description: 'Algorithm', example: 'RS256'),
new OA\Property(property: 'n', type: 'string', description: 'RSA modulus (Base64urlUInt-encoded)'),
new OA\Property(property: 'e', type: 'string', description: 'RSA exponent (Base64urlUInt-encoded)', example: 'AQAB'),
]
)
),
]
)]
class JWKSResponseSchema
{
}

#[OA\Schema(
Comment thread
matiasperrone-exo marked this conversation as resolved.
schema: 'OpenIDDiscoveryResponse',
title: 'OpenID Connect Discovery Document',
description: 'OpenID Provider Configuration per OpenID Connect Discovery 1.0',
type: 'object',
required: ['issuer', 'authorization_endpoint', 'token_endpoint', 'jwks_uri', 'response_types_supported', 'subject_types_supported', 'id_token_signing_alg_values_supported'],
properties: [
new OA\Property(property: 'issuer', type: 'string', format: 'uri', description: 'Issuer identifier URL'),
new OA\Property(property: 'authorization_endpoint', type: 'string', format: 'uri', description: 'Authorization endpoint URL'),
new OA\Property(property: 'token_endpoint', type: 'string', format: 'uri', description: 'Token endpoint URL'),
new OA\Property(property: 'userinfo_endpoint', type: 'string', format: 'uri', description: 'UserInfo endpoint URL'),
new OA\Property(property: 'revocation_endpoint', type: 'string', format: 'uri', description: 'Token revocation endpoint URL'),
new OA\Property(property: 'introspection_endpoint', type: 'string', format: 'uri', description: 'Token introspection endpoint URL'),
new OA\Property(property: 'jwks_uri', type: 'string', format: 'uri', description: 'JSON Web Key Set URL'),
new OA\Property(
property: 'scopes_supported',
type: 'array',
description: 'Supported OAuth2 scopes',
items: new OA\Items(type: 'string')
),
new OA\Property(
property: 'response_types_supported',
type: 'array',
description: 'Supported response types',
items: new OA\Items(type: 'string')
),
new OA\Property(
property: 'response_modes_supported',
type: 'array',
description: 'Supported response modes',
items: new OA\Items(type: 'string')
),
new OA\Property(
property: 'grant_types_supported',
type: 'array',
description: 'Supported grant types',
items: new OA\Items(type: 'string')
),
new OA\Property(
property: 'subject_types_supported',
type: 'array',
description: 'Supported subject types',
items: new OA\Items(type: 'string')
),
new OA\Property(
property: 'id_token_signing_alg_values_supported',
type: 'array',
description: 'Supported ID token signing algorithms',
items: new OA\Items(type: 'string')
),
new OA\Property(
property: 'code_challenge_methods_supported',
type: 'array',
description: 'Supported PKCE code challenge methods',
items: new OA\Items(type: 'string')
),
]
)]
class OpenIDDiscoveryResponseSchema
{
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
30 changes: 30 additions & 0 deletions app/Swagger/Requests/OAuth2AuthorizationRequestSchema.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace App\Swagger\schemas;

use OpenApi\Attributes as OA;

#[OA\Schema(
schema: 'OAuth2AuthorizationRequest',
title: 'OAuth2 Authorization Request',
description: 'Authorization request parameters per RFC 6749 §4.1.1 and OpenID Connect Core §3.1.2.1',
type: 'object',
required: ['response_type', 'client_id', 'redirect_uri'],
properties: [
new OA\Property(property: 'response_type', type: 'string', description: 'The OAuth 2.0 specification allows for registration of space-separated response_type parameter values. If a Response Type contains one of more space characters (%20), it is compared as a space-delimited list of values in which the order of values does not matter. Possible values are: code, token, id_token, otp, none. The "none" value cannot be used with any other response type value.'),
new OA\Property(property: 'client_id', type: 'string', description: 'OAuth2 client identifier'),
new OA\Property(property: 'redirect_uri', type: 'string', format: 'uri', description: 'Redirect URI'),
new OA\Property(property: 'scope', type: 'string', description: 'Space-delimited scopes'),
new OA\Property(property: 'state', type: 'string', description: 'Opaque state parameter'),
new OA\Property(property: 'approval_prompt', type: 'string', description: 'Indicates whether the user should be re-prompted for consent. The default is auto, so a given user should only see the consent page for a given set of scopes the first time through the sequence. If the value is force, then the user sees a consent page even if they previously gave consent to your application for a given set of scopes.', enum: ['auto', 'force']),
new OA\Property(property: 'access_type', type: 'string', description: 'Indicates whether your application needs to access an API when the user is not present at the browser. This parameter defaults to online. If your application needs to refresh access tokens when the user is not present at the browser, then use offline. This will result in your application obtaining a refresh token the first time your application exchanges an authorization code for a user.', enum: ['online', 'offline']),
new OA\Property(property: 'response_mode', type: 'string', description: 'OPTIONAL. Informs the Authorization Server of the mechanism to be used for returning Authorization Response parameters from the Authorization Endpoint. This use of this parameter is NOT RECOMMENDED with a value that specifies the same Response Mode as the default Response Mode for the Response Type used.\nThe default Response Mode for the OAuth 2.0 code Response Type is the query encoding. For purposes of this specification, the default Response Mode for the OAuth 2.0 token Response Type is the fragment encoding.', enum: ['query', 'fragment', 'form_post', 'direct']),
new OA\Property(property: 'code_challenge', type: 'string', description: 'PKCE code challenge'),
new OA\Property(property: 'code_challenge_method', type: 'string', description: 'Optional. PKCE challenge method', enum: ['plain', 'S256']),
new OA\Property(property: 'display', type: 'string', description: 'UI display preference (OIDC)', enum: ['page', 'popup', 'touch', 'wap', 'native']),
new OA\Property(property: 'tenant', type: 'string', description: 'Tenant identifier'),
]
)]
class OAuth2AuthorizationRequestSchema
{
}
22 changes: 22 additions & 0 deletions app/Swagger/Requests/OAuth2EndSessionRequestSchema.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace App\Swagger\schemas;

use OpenApi\Attributes as OA;

#[OA\Schema(
schema: 'OAuth2EndSessionRequest',
title: 'OAuth2 End Session Request',
description: 'RP-Initiated Logout request parameters per OpenID Connect Session Management 1.0',
type: 'object',
required: ['client_id'],
properties: [
new OA\Property(property: 'client_id', type: 'string', description: 'OAuth2 client identifier'),
new OA\Property(property: 'id_token_hint', type: 'string', description: 'Previously issued ID token'),
new OA\Property(property: 'post_logout_redirect_uri', type: 'string', format: 'uri', description: 'URI to redirect after logout'),
new OA\Property(property: 'state', type: 'string', description: 'Opaque state parameter'),
]
)]
class OAuth2EndSessionRequestSchema
{
}
21 changes: 21 additions & 0 deletions app/Swagger/Requests/OAuth2TokenIntrospectionRequestSchema.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace App\Swagger\schemas;

use OpenApi\Attributes as OA;

#[OA\Schema(
schema: 'OAuth2TokenIntrospectionRequest',
title: 'OAuth2 Token Introspection Request',
description: 'Token introspection request parameters per RFC 7662 §2.1',
type: 'object',
required: ['token'],
properties: [
new OA\Property(property: 'token', type: 'string', description: 'The token to introspect'),
new OA\Property(property: 'client_id', type: 'string', description: 'Client identifier (if not using HTTP Basic auth)'),
new OA\Property(property: 'client_secret', type: 'string', description: 'Client secret (if not using HTTP Basic auth)'),
]
)]
class OAuth2TokenIntrospectionRequestSchema
{
}
32 changes: 32 additions & 0 deletions app/Swagger/Requests/OAuth2TokenRequestSchema.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace App\Swagger\schemas;

use OpenApi\Attributes as OA;

#[OA\Schema(
schema: 'OAuth2TokenRequest',
title: 'OAuth2 Token Request',
description: 'Token request parameters per RFC 6749 §4.1.3. Fields required vary by grant_type.',
type: 'object',
required: ['grant_type'],
properties: [
new OA\Property(property: 'grant_type', type: 'string', description: 'OAuth2 grant type', enum: ['authorization_code', 'client_credentials', 'password', 'refresh_token', 'passwordless']),
new OA\Property(property: 'code', type: 'string', description: 'Authorization code (authorization_code grant)'),
new OA\Property(property: 'redirect_uri', type: 'string', format: 'uri', description: 'Redirect URI (must match the one used in authorization request)'),
new OA\Property(property: 'client_id', type: 'string', description: 'Client identifier (if not using HTTP Basic auth)'),
new OA\Property(property: 'client_secret', type: 'string', description: 'Client secret (if not using HTTP Basic auth)'),
new OA\Property(property: 'refresh_token', type: 'string', description: 'Refresh token (refresh_token grant)'),
new OA\Property(property: 'scope', type: 'string', description: 'Space-delimited scopes'),
new OA\Property(property: 'username', type: 'string', description: 'Username (password grant)'),
new OA\Property(property: 'password', type: 'string', description: 'Password (password grant)'),
new OA\Property(property: 'audience', type: 'string', description: 'Target audience (client_credentials grant)'),
new OA\Property(property: 'connection', type: 'string', description: 'Connection type (passwordless grant)', enum: ['sms', 'email']),
new OA\Property(property: 'send', type: 'string', description: 'Delivery method (passwordless grant)', enum: ['code', 'link']),
new OA\Property(property: 'email', type: 'string', description: 'Email address (passwordless grant)'),
new OA\Property(property: 'phone_number', type: 'string', description: 'Phone number (passwordless grant)'),
]
)]
class OAuth2TokenRequestSchema
{
}
22 changes: 22 additions & 0 deletions app/Swagger/Requests/OAuth2TokenRevocationRequestSchema.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace App\Swagger\schemas;

use OpenApi\Attributes as OA;

#[OA\Schema(
schema: 'OAuth2TokenRevocationRequest',
title: 'OAuth2 Token Revocation Request',
description: 'Token revocation request parameters per RFC 7009 §2.1',
type: 'object',
required: ['token'],
properties: [
new OA\Property(property: 'token', type: 'string', description: 'The token to revoke'),
new OA\Property(property: 'token_type_hint', type: 'string', description: 'Hint about the token type', enum: ['access_token', 'refresh_token']),
new OA\Property(property: 'client_id', type: 'string', description: 'Client identifier (if not using HTTP Basic auth)'),
new OA\Property(property: 'client_secret', type: 'string', description: 'Client secret (if not using HTTP Basic auth)'),
]
)]
class OAuth2TokenRevocationRequestSchema
{
}
27 changes: 27 additions & 0 deletions app/Swagger/Security/OAuth2ProviderControllerSecuritySchema.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace App\Swagger\schemas;

use OpenApi\Attributes as OA;

#[OA\SecurityScheme(
securityScheme: 'OAuth2ProviderSecurity',
type: 'oauth2',
description: 'OAuth2 client credentials authentication for protocol endpoints (token, revoke, introspection)',
flows: [
new OA\Flow(
flow: 'clientCredentials',
tokenUrl: L5_SWAGGER_CONST_TOKEN_URL,
Comment thread
matiasperrone-exo marked this conversation as resolved.
scopes: []
),
]
)]
#[OA\SecurityScheme(
securityScheme: 'OAuth2ProviderClientBasic',
type: 'http',
scheme: 'basic',
description: 'HTTP Basic authentication with OAuth2 client_id:client_secret (RFC 6749 §2.3.1).'
)]
class OAuth2ProviderControllerSecuritySchema
{
}
Loading