ResourceController.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. <?php
  2. namespace OAuth2\Controller;
  3. use OAuth2\TokenType\TokenTypeInterface;
  4. use OAuth2\Storage\AccessTokenInterface;
  5. use OAuth2\ScopeInterface;
  6. use OAuth2\RequestInterface;
  7. use OAuth2\ResponseInterface;
  8. use OAuth2\Scope;
  9. /**
  10. * @see ResourceControllerInterface
  11. */
  12. class ResourceController implements ResourceControllerInterface
  13. {
  14. /**
  15. * @var array
  16. */
  17. private $token;
  18. /**
  19. * @var TokenTypeInterface
  20. */
  21. protected $tokenType;
  22. /**
  23. * @var AccessTokenInterface
  24. */
  25. protected $tokenStorage;
  26. /**
  27. * @var array
  28. */
  29. protected $config;
  30. /**
  31. * @var ScopeInterface
  32. */
  33. protected $scopeUtil;
  34. /**
  35. * Constructor
  36. *
  37. * @param TokenTypeInterface $tokenType
  38. * @param AccessTokenInterface $tokenStorage
  39. * @param array $config
  40. * @param ScopeInterface $scopeUtil
  41. */
  42. public function __construct(TokenTypeInterface $tokenType, AccessTokenInterface $tokenStorage, $config = array(), ScopeInterface $scopeUtil = null)
  43. {
  44. $this->tokenType = $tokenType;
  45. $this->tokenStorage = $tokenStorage;
  46. $this->config = array_merge(array(
  47. 'www_realm' => 'Service',
  48. ), $config);
  49. if (is_null($scopeUtil)) {
  50. $scopeUtil = new Scope();
  51. }
  52. $this->scopeUtil = $scopeUtil;
  53. }
  54. /**
  55. * Verify the resource request
  56. *
  57. * @param RequestInterface $request
  58. * @param ResponseInterface $response
  59. * @param null $scope
  60. * @return bool
  61. */
  62. public function verifyResourceRequest(RequestInterface $request, ResponseInterface $response, $scope = null)
  63. {
  64. $token = $this->getAccessTokenData($request, $response);
  65. // Check if we have token data
  66. if (is_null($token)) {
  67. return false;
  68. }
  69. /**
  70. * Check scope, if provided
  71. * If token doesn't have a scope, it's null/empty, or it's insufficient, then throw 403
  72. * @see http://tools.ietf.org/html/rfc6750#section-3.1
  73. */
  74. if ($scope && (!isset($token["scope"]) || !$token["scope"] || !$this->scopeUtil->checkScope($scope, $token["scope"]))) {
  75. $response->setError(403, 'insufficient_scope', 'The request requires higher privileges than provided by the access token');
  76. $response->addHttpHeaders(array(
  77. 'WWW-Authenticate' => sprintf('%s realm="%s", scope="%s", error="%s", error_description="%s"',
  78. $this->tokenType->getTokenType(),
  79. $this->config['www_realm'],
  80. $scope,
  81. $response->getParameter('error'),
  82. $response->getParameter('error_description')
  83. )
  84. ));
  85. return false;
  86. }
  87. // allow retrieval of the token
  88. $this->token = $token;
  89. return (bool) $token;
  90. }
  91. /**
  92. * Get access token data.
  93. *
  94. * @param RequestInterface $request
  95. * @param ResponseInterface $response
  96. * @return array|null
  97. */
  98. public function getAccessTokenData(RequestInterface $request, ResponseInterface $response)
  99. {
  100. // Get the token parameter
  101. if ($token_param = $this->tokenType->getAccessTokenParameter($request, $response)) {
  102. // Get the stored token data (from the implementing subclass)
  103. // Check we have a well formed token
  104. // Check token expiration (expires is a mandatory paramter)
  105. if (!$token = $this->tokenStorage->getAccessToken($token_param)) {
  106. $response->setError(401, 'invalid_token', 'The access token provided is invalid');
  107. } elseif (!isset($token["expires"]) || !isset($token["client_id"])) {
  108. $response->setError(401, 'malformed_token', 'Malformed token (missing "expires")');
  109. } elseif (time() > $token["expires"]) {
  110. $response->setError(401, 'invalid_token', 'The access token provided has expired');
  111. } else {
  112. return $token;
  113. }
  114. }
  115. $authHeader = sprintf('%s realm="%s"', $this->tokenType->getTokenType(), $this->config['www_realm']);
  116. if ($error = $response->getParameter('error')) {
  117. $authHeader = sprintf('%s, error="%s"', $authHeader, $error);
  118. if ($error_description = $response->getParameter('error_description')) {
  119. $authHeader = sprintf('%s, error_description="%s"', $authHeader, $error_description);
  120. }
  121. }
  122. $response->addHttpHeaders(array('WWW-Authenticate' => $authHeader));
  123. return null;
  124. }
  125. /**
  126. * convenience method to allow retrieval of the token.
  127. *
  128. * @return array
  129. */
  130. public function getToken()
  131. {
  132. return $this->token;
  133. }
  134. }