728 lines
30 KiB
PHP
728 lines
30 KiB
PHP
<?php
|
|
|
|
//ini_set('display_errors', 1);
|
|
//error_reporting(E_ALL | E_STRICT);
|
|
|
|
// Regex to filter out the client identifier
|
|
// (described in Section 2 of IETF draft)
|
|
// IETF draft does not prescribe a format for these, however
|
|
// I've arbitrarily chosen alphanumeric strings with hyphens and underscores, 3-12 characters long
|
|
// Feel free to change.
|
|
define("REGEX_CLIENT_ID", "/^[a-z0-9-_]{3,12}$/i");
|
|
|
|
// Used to define the name of the OAuth access token parameter (POST/GET/etc.)
|
|
// IETF Draft sections 5.2 and 5.3 specify that it should be called "oauth_token"
|
|
// but other implementations use things like "access_token"
|
|
// I won't be heartbroken if you change it, but it might be better to adhere to the spec
|
|
define("OAUTH_TOKEN_PARAM_NAME", "oauth_token");
|
|
|
|
// Client types (for client authorization)
|
|
//define("WEB_SERVER_CLIENT_TYPE", "web_server");
|
|
//define("USER_AGENT_CLIENT_TYPE", "user_agent");
|
|
//define("REGEX_CLIENT_TYPE", "/^(web_server|user_agent)$/");
|
|
define("ACCESS_TOKEN_AUTH_RESPONSE_TYPE", "token");
|
|
define("AUTH_CODE_AUTH_RESPONSE_TYPE", "code");
|
|
define("CODE_AND_TOKEN_AUTH_RESPONSE_TYPE", "code-and-token");
|
|
define("REGEX_AUTH_RESPONSE_TYPE", "/^(token|code|code-and-token)$/");
|
|
|
|
// Grant Types (for token obtaining)
|
|
define("AUTH_CODE_GRANT_TYPE", "authorization-code");
|
|
define("USER_CREDENTIALS_GRANT_TYPE", "basic-credentials");
|
|
define("ASSERTION_GRANT_TYPE", "assertion");
|
|
define("REFRESH_TOKEN_GRANT_TYPE", "refresh-token");
|
|
define("NONE_GRANT_TYPE", "none");
|
|
define("REGEX_TOKEN_GRANT_TYPE", "/^(authorization-code|basic-credentials|assertion|refresh-token|none)$/");
|
|
|
|
/* Error handling constants */
|
|
|
|
// HTTP status codes
|
|
define("ERROR_NOT_FOUND", "404 Not Found");
|
|
define("ERROR_BAD_REQUEST", "400 Bad Request");
|
|
|
|
// TODO: Extend for i18n
|
|
|
|
// "Official" OAuth 2.0 errors
|
|
define("ERROR_REDIRECT_URI_MISMATCH", "redirect-uri-mismatch");
|
|
define("ERROR_INVALID_CLIENT_CREDENTIALS", "invalid-client-credentials");
|
|
define("ERROR_UNAUTHORIZED_CLIENT", "unauthorized-client");
|
|
define("ERROR_USER_DENIED", "access-denied");
|
|
define("ERROR_INVALID_REQUEST", "invalid-request");
|
|
define("ERROR_INVALID_CLIENT_ID", "invalid-client-id");
|
|
define("ERROR_UNSUPPORTED_RESPONSE_TYPE", "unsupported-response-type");
|
|
define("ERROR_INVALID_SCOPE", "invalid-scope");
|
|
define("ERROR_INVALID_GRANT", "invalid-grant");
|
|
|
|
// Protected resource errors
|
|
define("ERROR_INVALID_TOKEN", "invalid-token");
|
|
define("ERROR_EXPIRED_TOKEN", "expired-token");
|
|
define("ERROR_INSUFFICIENT_SCOPE", "insufficient-scope");
|
|
|
|
// Messages
|
|
define("ERROR_INVALID_RESPONSE_TYPE", "Invalid response type.");
|
|
|
|
// Errors that we made up
|
|
|
|
// Error for trying to use a grant type that we haven't implemented
|
|
define("ERROR_UNSUPPORTED_GRANT_TYPE", "unsupported-grant-type");
|
|
|
|
abstract class OAuth2 {
|
|
|
|
/* Subclasses must implement the following functions */
|
|
|
|
// Make sure that the client id is valid
|
|
// If a secret is required, check that they've given the right one
|
|
// Must return false if the client credentials are invalid
|
|
abstract protected function auth_client_credentials($client_id, $client_secret = null);
|
|
|
|
// OAuth says we should store request URIs for each registered client
|
|
// Implement this function to grab the stored URI for a given client id
|
|
// Must return false if the given client does not exist or is invalid
|
|
abstract protected function get_redirect_uri($client_id);
|
|
|
|
// We need to store and retrieve access token data as we create and verify tokens
|
|
// Implement these functions to do just that
|
|
|
|
// Look up the supplied token id from storage, and return an array like:
|
|
//
|
|
// array(
|
|
// "client_id" => <stored client id>,
|
|
// "expires" => <stored expiration timestamp>,
|
|
// "scope" => <stored scope (may be null)
|
|
// )
|
|
//
|
|
// Return null if the supplied token is invalid
|
|
//
|
|
abstract protected function get_access_token($token_id);
|
|
|
|
// Store the supplied values
|
|
abstract protected function store_access_token($token_id, $client_id, $expires, $scope = null);
|
|
|
|
/*
|
|
*
|
|
* Stuff that should get overridden by subclasses
|
|
*
|
|
* I don't want to make these abstract, because then subclasses would have
|
|
* to implement all of them, which is too much work.
|
|
*
|
|
* So they're just stubs. Override the ones you need.
|
|
*
|
|
*/
|
|
|
|
// You should override this function with something,
|
|
// or else your OAuth provider won't support any grant types!
|
|
protected function get_supported_grant_types() {
|
|
// If you support all grant types, then you'd do:
|
|
// return array(
|
|
// AUTH_CODE_GRANT_TYPE,
|
|
// USER_CREDENTIALS_GRANT_TYPE,
|
|
// ASSERTION_GRANT_TYPE,
|
|
// REFRESH_TOKEN_GRANT_TYPE,
|
|
// NONE_GRANT_TYPE
|
|
// );
|
|
|
|
return array();
|
|
}
|
|
|
|
// You should override this function with your supported response types
|
|
protected function get_supported_auth_response_types() {
|
|
return array(
|
|
AUTH_CODE_AUTH_RESPONSE_TYPE,
|
|
ACCESS_TOKEN_AUTH_RESPONSE_TYPE,
|
|
CODE_AND_TOKEN_AUTH_RESPONSE_TYPE
|
|
);
|
|
}
|
|
|
|
// If you want to support scope use, then have this function return a list
|
|
// of all acceptable scopes (used to throw the invalid-scope error)
|
|
protected function get_supported_scopes() {
|
|
// Example:
|
|
// return array("my-friends", "photos", "whatever-else");
|
|
return array();
|
|
}
|
|
|
|
// If you want to restrict clients to certain authorization response types,
|
|
// override this function
|
|
// Given a client identifier and auth type, return true or false
|
|
// (auth type would be one of the values contained in REGEX_AUTH_RESPONSE_TYPE)
|
|
protected function authorize_client_response_type($client_id, $response_type) {
|
|
return true;
|
|
} |