Skip to content

Commit

Permalink
Oauth2Server MVC (#310)
Browse files Browse the repository at this point in the history
Renane callback uri field to redirect uri

Fetch access token
  • Loading branch information
Ioannis authored Apr 28, 2025
1 parent 532b63b commit 576f8c2
Show file tree
Hide file tree
Showing 8 changed files with 739 additions and 4 deletions.
51 changes: 51 additions & 0 deletions app/plugins/CoreServer/resources/locales/en_US/core_server.po
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ msgstr "{0,plural,=1{SMTP Server} other{SMTP Servers}}"
msgid "controller.SqlServers"
msgstr "{0,plural,=1{SQL Server} other{SQL Servers}}"

msgid "controller.Oauth2Servers"
msgstr "{0,plural,=1{Oauth2 Server} other{Oauth2 Servers}}"

msgid "enumeration.HttpAuthTypeEnum.BA"
msgstr "Basic"

Expand All @@ -43,6 +46,12 @@ msgstr "Bearer"
msgid "enumeration.HttpAuthTypeEnum.X"
msgstr "None"

msgid "enumeration.Oauth2GrandTypesEnum.AC"
msgstr "Authorization Code"

msgid "enumeration.Oauth2GrandTypesEnum.CC"
msgstr "Client Credentials"

msgid "enumeration.RdbmsTypeEnum.LT"
msgstr "SQLite"

Expand All @@ -61,6 +70,21 @@ msgstr "Oracle"
msgid "enumeration.RdbmsTypeEnum.PG"
msgstr "Postgres"

msgid "error.Oauth2Servers.callback"
msgstr "Incorrect parameters in callback"

msgid "error.Oauth2Servers.state"
msgstr "Invalid state received in callback"

msgid "error.Oauth2Servers.token"
msgstr "Error obtaining access token: {0}"

msgid "info.Oauth2Servers.token.ok"
msgstr "Access Token Obtained"

msgid "info.Oauth2Servers.token.obtain"
msgstr "Obtain New Token"

msgid "field.auth_type"
msgstr "Authentication Type"

Expand All @@ -70,6 +94,33 @@ msgstr "Skip SSL Verification"
msgid "field.MatchServers.api_endpoint"
msgstr "API Endpoint"

msgid "field.Oauth2Servers.access_token"
msgstr "Access Token"

msgid "field.Oauth2Servers.access_token.desc"
msgstr "Save any changes to the configuration before obtaining a new token"

msgid "field.Oauth2Servers.clientid"
msgstr "Client ID"

msgid "field.Oauth2Servers.client_secret"
msgstr "Client Secret"

msgid "field.Oauth2Servers.access_grant_type"
msgstr "Access Token Grant Type"

msgid "field.Oauth2Servers.url"
msgstr "Server URL"

msgid "field.Oauth2Servers.redirect_uri"
msgstr "Redirect URI"

msgid "field.Oauth2Servers.scope"
msgstr "Scopes"

msgid "info.Oauth2Servers.access_token.ok"
msgstr "Access Token Obtained"

msgid "field.SmtpServers.default_from"
msgstr "Default From Address"

Expand Down
184 changes: 184 additions & 0 deletions app/plugins/CoreServer/src/Controller/Oauth2ServersController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
<?php
/**
* COmanage Registry Oauth2 Servers Controller
*
* Portions licensed to the University Corporation for Advanced Internet
* Development, Inc. ("UCAID") under one or more contributor license agreements.
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership.
*
* UCAID licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @link https://www.internet2.edu/comanage COmanage Project
* @package registry-plugins
* @since COmanage Registry v5.2.0
* @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
*/

declare(strict_types=1);

namespace CoreServer\Controller;

use App\Controller\StandardPluginController;
use Cake\Event\EventInterface;
use CoreServer\Lib\Enum\Oauth2GrandTypesEnum;

class Oauth2ServersController extends StandardPluginController
{
public $paginate = [
'order' => [
'OauthServers.url' => 'asc'
]
];


/**
* Callback run prior to the request render.
*
* @param EventInterface $event Cake Event
*
* @since COmanage Registry v5.2.0
*/

public function beforeRender(EventInterface $event)
{
// Generate the Redirect URI

if ($this->getRequest()->getParam('action') === 'edit') {
$id = $this->getRequest()->getParam('pass')[0] ?? null; // Assuming $id comes from passed arguments
$this->set('vv_redirect_uri', $this->Oauth2Servers->redirectUri($id));
}

return parent::beforeRender($event);
}

/**
* OAuth callback.
*
* @param integer $id Oauth2Server ID
* @since COmanage Registry v5.2.0
*/

public function callback($id): void
{
$this->autoRender = false;
try {
$request = $this->getRequest();
$code = $request->getQuery('code');
$state = $request->getQuery('state');

if (empty($code) || empty($state)) {
throw new \RuntimeException(__d('core_server', 'error.Oauth2Servers.callback'));
}

// Verify that state is our hashed session ID, as per RFC6749 §10.12
// recommendations to prevent CSRF.
// https://tools.ietf.org/html/rfc6749#section-10.12

// Access session from the request object
$sessionId = $request->getSession()->id();

if ($state != hash('sha256', $sessionId)) {
throw new \RuntimeException(__d('core_server', 'error.Oauth2Servers.state'));
}

$response = $this->Oauth2Servers->exchangeCode(
$id,
$code,
$this->Oauth2Servers->redirectUri((int)$id),
);

$this->Flash->success(__d('core_server', 'info.Oauth2Servers.access_token.ok'));
} catch (\Exception $e) {
$this->Flash->error($e->getMessage());
}

$this->performRedirect();
}

/**
* Obtain an access token for a Oauth2Server.
*
* @since COmanage Registry v5.2.0
* @param integer $id Oauth2Server ID
*/

public function token($id): void
{
// Pull our configuration, initially to find out what type of grant type we need
$osrvr = $this->Oauth2Servers->get($id);

if(!$osrvr) {
$this->Flash->error(__d('error', 'notfound', [__d('core_server', 'controller.Oauth2Servers')]));
$this->performRedirect();
}

try {
switch($osrvr->access_grant_type) {
case Oauth2GrandTypesEnum::AuthorizationCode:
// Issue a redirect to the server
$targetUrl = $osrvr->url
. '/authorize?response_type=code'
. '&client_id=' . $osrvr->clientid
. '&redirect_uri=' . urlencode($this->Oauth2Servers->redirectUri($id))
. '&state=' . hash('sha256', session_id());
// Scope is optional
if(!empty($osrvr->scope)) {
$targetUrl .= '&scope='. str_replace(' ', '%20', $osrvr->scope);
}

$this->redirect($targetUrl);
break;
case Oauth2GrandTypesEnum::ClientCredentials:
// Make a direct call to the server
$this->Oauth2Servers->obtainToken((int)$id, 'client_credentials');
$this->Flash->success(__d('core_server', 'info.Oauth2Servers.access_token.ok'));
break;
default:
// No other flows currently supported
throw new \LogicException('Not implemented yet.');
}
} catch(\Exception $e) {
$this->Flash->error($e->getMessage());
}

$this->performRedirect();
}

/**
* Perform a redirect back to the controller's default view.
*
* @since COmanage Registry v5.2.0
*/

function performRedirect(): void
{
$target = [];
$target['plugin'] = null;

if (!empty($this->getRequest()->getParam('pass')[0])) {
$target['plugin'] = 'CoreServer';
$target['controller'] = 'Oauth2Servers';
$target['action'] = 'edit';
$target[] = filter_var($this->getRequest()->getParam('pass')[0], FILTER_SANITIZE_SPECIAL_CHARS);
} else {
$target['controller'] = 'Servers';
$target['action'] = 'index';
$target['?'] = [
'co_id' => $this->getCOID()
];
}

$this->redirect($target);
}
}
39 changes: 39 additions & 0 deletions app/plugins/CoreServer/src/Lib/Enum/Oauth2GrandTypesEnum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php
/**
* COmanage Registry Grand Types Enum
*
* Portions licensed to the University Corporation for Advanced Internet
* Development, Inc. ("UCAID") under one or more contributor license agreements.
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership.
*
* UCAID licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @link https://www.internet2.edu/comanage COmanage Project
* @package registry-plugins
* @since COmanage Registry v5.2.0
* @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
*/

declare(strict_types = 1);

namespace CoreServer\Lib\Enum;

use App\Lib\Enum\StandardEnum;

class Oauth2GrandTypesEnum extends StandardEnum
{
const AuthorizationCode = 'AC';
const ClientCredentials = 'CC';
// We don't currently support Implicit or Password Credentials
}
49 changes: 49 additions & 0 deletions app/plugins/CoreServer/src/Model/Entity/Oauth2Server.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
/**
* COmanage Registry Oauth2 Server Entity
*
* Portions licensed to the University Corporation for Advanced Internet
* Development, Inc. ("UCAID") under one or more contributor license agreements.
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership.
*
* UCAID licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @link https://www.internet2.edu/comanage COmanage Project
* @package registry-plugins
* @since COmanage Registry v5.2.0
* @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
*/

declare(strict_types=1);

namespace CoreServer\Model\Entity;

use Cake\ORM\Entity;

class Oauth2Server extends Entity {
/**
* Fields that can be mass assigned using newEntity() or patchEntity().
*
* Note that when '*' is set to true, this allows all unspecified fields to
* be mass assigned. For security purposes, it is advised to set '*' to false
* (or remove it), and explicitly make individual fields accessible as needed.
*
* @var array<string, bool>
*/
protected $_accessible = [
'*' => true,
'id' => false,
'slug' => false,
];
}
Loading

0 comments on commit 576f8c2

Please sign in to comment.