Bearer.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. <?php
  2. namespace OAuth2\TokenType;
  3. use OAuth2\RequestInterface;
  4. use OAuth2\ResponseInterface;
  5. /**
  6. *
  7. */
  8. class Bearer implements TokenTypeInterface
  9. {
  10. private $config;
  11. public function __construct(array $config = array())
  12. {
  13. $this->config = array_merge(array(
  14. 'token_param_name' => 'access_token',
  15. 'token_bearer_header_name' => 'Bearer',
  16. ), $config);
  17. }
  18. public function getTokenType()
  19. {
  20. return 'Bearer';
  21. }
  22. /**
  23. * Check if the request has supplied token
  24. *
  25. * @see https://github.com/bshaffer/oauth2-server-php/issues/349#issuecomment-37993588
  26. */
  27. public function requestHasToken(RequestInterface $request)
  28. {
  29. $headers = $request->headers('AUTHORIZATION');
  30. // check the header, then the querystring, then the request body
  31. return !empty($headers) || (bool) ($request->request($this->config['token_param_name'])) || (bool) ($request->query($this->config['token_param_name']));
  32. }
  33. /**
  34. * This is a convenience function that can be used to get the token, which can then
  35. * be passed to getAccessTokenData(). The constraints specified by the draft are
  36. * attempted to be adheared to in this method.
  37. *
  38. * As per the Bearer spec (draft 8, section 2) - there are three ways for a client
  39. * to specify the bearer token, in order of preference: Authorization Header,
  40. * POST and GET.
  41. *
  42. * NB: Resource servers MUST accept tokens via the Authorization scheme
  43. * (http://tools.ietf.org/html/rfc6750#section-2).
  44. *
  45. * @todo Should we enforce TLS/SSL in this function?
  46. *
  47. * @see http://tools.ietf.org/html/rfc6750#section-2.1
  48. * @see http://tools.ietf.org/html/rfc6750#section-2.2
  49. * @see http://tools.ietf.org/html/rfc6750#section-2.3
  50. *
  51. * Old Android version bug (at least with version 2.2)
  52. * @see http://code.google.com/p/android/issues/detail?id=6684
  53. *
  54. */
  55. public function getAccessTokenParameter(RequestInterface $request, ResponseInterface $response)
  56. {
  57. $headers = $request->headers('AUTHORIZATION');
  58. /**
  59. * Ensure more than one method is not used for including an
  60. * access token
  61. *
  62. * @see http://tools.ietf.org/html/rfc6750#section-3.1
  63. */
  64. $methodsUsed = !empty($headers) + (bool) ($request->query($this->config['token_param_name'])) + (bool) ($request->request($this->config['token_param_name']));
  65. if ($methodsUsed > 1) {
  66. $response->setError(400, 'invalid_request', 'Only one method may be used to authenticate at a time (Auth header, GET or POST)');
  67. return null;
  68. }
  69. /**
  70. * If no authentication is provided, set the status code
  71. * to 401 and return no other error information
  72. *
  73. * @see http://tools.ietf.org/html/rfc6750#section-3.1
  74. */
  75. if ($methodsUsed == 0) {
  76. $response->setStatusCode(401);
  77. return null;
  78. }
  79. // HEADER: Get the access token from the header
  80. if (!empty($headers)) {
  81. if (!preg_match('/' . $this->config['token_bearer_header_name'] . '\s(\S+)/i', $headers, $matches)) {
  82. $response->setError(400, 'invalid_request', 'Malformed auth header');
  83. return null;
  84. }
  85. return $matches[1];
  86. }
  87. if ($request->request($this->config['token_param_name'])) {
  88. // // POST: Get the token from POST data
  89. if (!in_array(strtolower($request->server('REQUEST_METHOD')), array('post', 'put'))) {
  90. $response->setError(400, 'invalid_request', 'When putting the token in the body, the method must be POST or PUT', '#section-2.2');
  91. return null;
  92. }
  93. $contentType = $request->server('CONTENT_TYPE');
  94. if (false !== $pos = strpos($contentType, ';')) {
  95. $contentType = substr($contentType, 0, $pos);
  96. }
  97. if ($contentType !== null && $contentType != 'application/x-www-form-urlencoded') {
  98. // IETF specifies content-type. NB: Not all webservers populate this _SERVER variable
  99. // @see http://tools.ietf.org/html/rfc6750#section-2.2
  100. $response->setError(400, 'invalid_request', 'The content type for POST requests must be "application/x-www-form-urlencoded"');
  101. return null;
  102. }
  103. return $request->request($this->config['token_param_name']);
  104. }
  105. // GET method
  106. return $request->query($this->config['token_param_name']);
  107. }
  108. }