diff options
Diffstat (limited to 'library/oauth2/src/OAuth2/OpenID/Controller')
4 files changed, 197 insertions, 0 deletions
diff --git a/library/oauth2/src/OAuth2/OpenID/Controller/AuthorizeController.php b/library/oauth2/src/OAuth2/OpenID/Controller/AuthorizeController.php new file mode 100644 index 000000000..c9b5c6af7 --- /dev/null +++ b/library/oauth2/src/OAuth2/OpenID/Controller/AuthorizeController.php @@ -0,0 +1,106 @@ +<?php + +namespace OAuth2\OpenID\Controller; + +use OAuth2\Controller\AuthorizeController as BaseAuthorizeController; +use OAuth2\RequestInterface; +use OAuth2\ResponseInterface; + +/** + * @see OAuth2\Controller\AuthorizeControllerInterface + */ +class AuthorizeController extends BaseAuthorizeController implements AuthorizeControllerInterface +{ + private $nonce; + + protected function setNotAuthorizedResponse(RequestInterface $request, ResponseInterface $response, $redirect_uri, $user_id = null) + { + $prompt = $request->query('prompt', 'consent'); + if ($prompt == 'none') { + if (is_null($user_id)) { + $error = 'login_required'; + $error_message = 'The user must log in'; + } else { + $error = 'interaction_required'; + $error_message = 'The user must grant access to your application'; + } + } else { + $error = 'consent_required'; + $error_message = 'The user denied access to your application'; + } + + $response->setRedirect($this->config['redirect_status_code'], $redirect_uri, $this->getState(), $error, $error_message); + } + + protected function buildAuthorizeParameters($request, $response, $user_id) + { + if (!$params = parent::buildAuthorizeParameters($request, $response, $user_id)) { + return; + } + + // Generate an id token if needed. + if ($this->needsIdToken($this->getScope()) && $this->getResponseType() == self::RESPONSE_TYPE_AUTHORIZATION_CODE) { + $params['id_token'] = $this->responseTypes['id_token']->createIdToken($this->getClientId(), $user_id, $this->nonce); + } + + // add the nonce to return with the redirect URI + $params['nonce'] = $this->nonce; + + return $params; + } + + public function validateAuthorizeRequest(RequestInterface $request, ResponseInterface $response) + { + if (!parent::validateAuthorizeRequest($request, $response)) { + return false; + } + + $nonce = $request->query('nonce'); + + // Validate required nonce for "id_token" and "id_token token" + if (!$nonce && in_array($this->getResponseType(), array(self::RESPONSE_TYPE_ID_TOKEN, self::RESPONSE_TYPE_ID_TOKEN_TOKEN))) { + $response->setError(400, 'invalid_nonce', 'This application requires you specify a nonce parameter'); + + return false; + } + + $this->nonce = $nonce; + + return true; + } + + protected function getValidResponseTypes() + { + return array( + self::RESPONSE_TYPE_ACCESS_TOKEN, + self::RESPONSE_TYPE_AUTHORIZATION_CODE, + self::RESPONSE_TYPE_ID_TOKEN, + self::RESPONSE_TYPE_ID_TOKEN_TOKEN, + self::RESPONSE_TYPE_CODE_ID_TOKEN, + ); + } + + /** + * Returns whether the current request needs to generate an id token. + * + * ID Tokens are a part of the OpenID Connect specification, so this + * method checks whether OpenID Connect is enabled in the server settings + * and whether the openid scope was requested. + * + * @param $request_scope + * A space-separated string of scopes. + * + * @return + * TRUE if an id token is needed, FALSE otherwise. + */ + public function needsIdToken($request_scope) + { + // see if the "openid" scope exists in the requested scope + return $this->scopeUtil->checkScope('openid', $request_scope); + } + + public function getNonce() + { + return $this->nonce; + } +} diff --git a/library/oauth2/src/OAuth2/OpenID/Controller/AuthorizeControllerInterface.php b/library/oauth2/src/OAuth2/OpenID/Controller/AuthorizeControllerInterface.php new file mode 100644 index 000000000..1e231d844 --- /dev/null +++ b/library/oauth2/src/OAuth2/OpenID/Controller/AuthorizeControllerInterface.php @@ -0,0 +1,10 @@ +<?php + +namespace OAuth2\OpenID\Controller; + +interface AuthorizeControllerInterface +{ + const RESPONSE_TYPE_ID_TOKEN = 'id_token'; + const RESPONSE_TYPE_ID_TOKEN_TOKEN = 'id_token token'; + const RESPONSE_TYPE_CODE_ID_TOKEN = 'code id_token'; +} diff --git a/library/oauth2/src/OAuth2/OpenID/Controller/UserInfoController.php b/library/oauth2/src/OAuth2/OpenID/Controller/UserInfoController.php new file mode 100644 index 000000000..30cb942d0 --- /dev/null +++ b/library/oauth2/src/OAuth2/OpenID/Controller/UserInfoController.php @@ -0,0 +1,58 @@ +<?php + +namespace OAuth2\OpenID\Controller; + +use OAuth2\Scope; +use OAuth2\TokenType\TokenTypeInterface; +use OAuth2\Storage\AccessTokenInterface; +use OAuth2\OpenID\Storage\UserClaimsInterface; +use OAuth2\Controller\ResourceController; +use OAuth2\ScopeInterface; +use OAuth2\RequestInterface; +use OAuth2\ResponseInterface; + +/** + * @see OAuth2\Controller\UserInfoControllerInterface + */ +class UserInfoController extends ResourceController implements UserInfoControllerInterface +{ + private $token; + + protected $tokenType; + protected $tokenStorage; + protected $userClaimsStorage; + protected $config; + protected $scopeUtil; + + public function __construct(TokenTypeInterface $tokenType, AccessTokenInterface $tokenStorage, UserClaimsInterface $userClaimsStorage, $config = array(), ScopeInterface $scopeUtil = null) + { + $this->tokenType = $tokenType; + $this->tokenStorage = $tokenStorage; + $this->userClaimsStorage = $userClaimsStorage; + + $this->config = array_merge(array( + 'www_realm' => 'Service', + ), $config); + + if (is_null($scopeUtil)) { + $scopeUtil = new Scope(); + } + $this->scopeUtil = $scopeUtil; + } + + public function handleUserInfoRequest(RequestInterface $request, ResponseInterface $response) + { + if (!$this->verifyResourceRequest($request, $response, 'openid')) { + return; + } + + $token = $this->getToken(); + $claims = $this->userClaimsStorage->getUserClaims($token['user_id'], $token['scope']); + // The sub Claim MUST always be returned in the UserInfo Response. + // http://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse + $claims += array( + 'sub' => $token['user_id'], + ); + $response->addParameters($claims); + } +} diff --git a/library/oauth2/src/OAuth2/OpenID/Controller/UserInfoControllerInterface.php b/library/oauth2/src/OAuth2/OpenID/Controller/UserInfoControllerInterface.php new file mode 100644 index 000000000..a89049d49 --- /dev/null +++ b/library/oauth2/src/OAuth2/OpenID/Controller/UserInfoControllerInterface.php @@ -0,0 +1,23 @@ +<?php + +namespace OAuth2\OpenID\Controller; + +use OAuth2\RequestInterface; +use OAuth2\ResponseInterface; + +/** + * This controller is called when the user claims for OpenID Connect's + * UserInfo endpoint should be returned. + * + * ex: + * > $response = new OAuth2\Response(); + * > $userInfoController->handleUserInfoRequest( + * > OAuth2\Request::createFromGlobals(), + * > $response; + * > $response->send(); + * + */ +interface UserInfoControllerInterface +{ + public function handleUserInfoRequest(RequestInterface $request, ResponseInterface $response); +} |