OobAuthorizationController.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. <?php
  2. namespace App\Http\Controllers\OAuth;
  3. use Laravel\Passport\Http\Controllers\ApproveAuthorizationController;
  4. use Illuminate\Http\Request;
  5. use League\OAuth2\Server\Exception\OAuthServerException;
  6. use Nyholm\Psr7\Response as Psr7Response;
  7. class OobAuthorizationController extends ApproveAuthorizationController
  8. {
  9. /**
  10. * Approve the authorization request.
  11. *
  12. * @param Request $request
  13. * @return \Illuminate\Http\Response
  14. */
  15. public function approve(Request $request)
  16. {
  17. $this->assertValidAuthToken($request);
  18. $authRequest = $this->getAuthRequestFromSession($request);
  19. $authRequest->setAuthorizationApproved(true);
  20. return $this->withErrorHandling(function () use ($authRequest) {
  21. $response = $this->server->completeAuthorizationRequest($authRequest, new Psr7Response);
  22. if ($this->isOutOfBandRequest($authRequest)) {
  23. $code = $this->extractAuthorizationCode($response);
  24. return response()->json([
  25. 'code' => $code,
  26. 'state' => $authRequest->getState()
  27. ]);
  28. }
  29. return $this->convertResponse($response);
  30. });
  31. }
  32. /**
  33. * Check if the request is an out-of-band OAuth request.
  34. *
  35. * @param \League\OAuth2\Server\RequestTypes\AuthorizationRequest $authRequest
  36. * @return bool
  37. */
  38. protected function isOutOfBandRequest($authRequest)
  39. {
  40. return $authRequest->getRedirectUri() === 'urn:ietf:wg:oauth:2.0:oob';
  41. }
  42. /**
  43. * Extract the authorization code from the PSR-7 response.
  44. *
  45. * @param \Psr\Http\Message\ResponseInterface $response
  46. * @return string
  47. * @throws \League\OAuth2\Server\Exception\OAuthServerException
  48. */
  49. protected function extractAuthorizationCode($response)
  50. {
  51. $location = $response->getHeader('Location')[0] ?? '';
  52. if (empty($location)) {
  53. throw OAuthServerException::serverError('Missing authorization code in response');
  54. }
  55. parse_str(parse_url($location, PHP_URL_QUERY), $params);
  56. if (!isset($params['code'])) {
  57. throw OAuthServerException::serverError('Invalid authorization code format');
  58. }
  59. return $params['code'];
  60. }
  61. /**
  62. * Handle OAuth errors for both redirect and OOB flows.
  63. *
  64. * @param \Closure $callback
  65. * @return \Illuminate\Http\Response
  66. */
  67. protected function withErrorHandling($callback)
  68. {
  69. try {
  70. return $callback();
  71. } catch (OAuthServerException $e) {
  72. if ($this->isOutOfBandRequest($this->getAuthRequestFromSession(request()))) {
  73. return response()->json([
  74. 'error' => $e->getErrorType(),
  75. 'message' => $e->getMessage(),
  76. 'hint' => $e->getHint()
  77. ], $e->getHttpStatusCode());
  78. }
  79. return $this->convertResponse(
  80. $e->generateHttpResponse(new Psr7Response)
  81. );
  82. }
  83. }
  84. }