Skip to content

Commit

Permalink
Merge branch 'v1.2' into v1.1
Browse files Browse the repository at this point in the history
  • Loading branch information
cydrickn authored Jul 14, 2024
2 parents 3edbf54 + 5cf743f commit 8beb254
Show file tree
Hide file tree
Showing 33 changed files with 1,698 additions and 39 deletions.
4 changes: 3 additions & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ REDIS_DATABASE=0

SERVER_HOST=0.0.0.0
SERVER_PORT=8080
SERVER_WORKERNUM=3
SERVER_WORKERNUM=1

CONFIG_FILE=./config.json
20 changes: 18 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,27 @@ That will now run the server

## Advance Profile Feature Support

The current version does not support Advance Profile Features
### Authentication

| Feature | Static | Dynamic |
|------------|---------|---------|
| Anonymous | ✓ | ✓ |
| Ticket | ✓ | ✓ |
| Wamp-CRA | ✗ | ✗ |
| Wamp-SCRA | ✗ | ✗ |
| Cryptosign | ✗ | ✗ |
| TLS | ✗ | ✗ |
| Cookie | ✗ | ✗ |

**Additional Authentication**

- [ ] Add Feature
- [ ] Add checking of role


## TODOs

- [ ] Implement CBOR Serializer https://wamp-proto.org/wamp_bp_latest_ietf.html#name-serializers
- [ ] Implement Advance Profile
- [ ] Remove Dependencies from Thruway Common
- [ ] Add OpenSwoole Table Adapter as Data Provider
- [ ] Add OpenSwoole Table Adapter as Data Provider
18 changes: 16 additions & 2 deletions bin/server.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
use Octamp\Wamp\Wamp;
use Symfony\Component\Dotenv\Dotenv;

require_once __DIR__ . '/../vendor/autoload.php';
$loader = require_once __DIR__ . '/../vendor/autoload.php';

$env = new Dotenv();
$env->loadEnv(dirname(__DIR__ . '') . '/.env');
$env->loadEnv(dirname(__DIR__) . '/.env');


$redisOptions = [
Expand All @@ -32,6 +32,20 @@
host: $_ENV['SERVER_HOST'],
port: $_ENV['SERVER_PORT'],
workerNum: $_ENV['SERVER_WORKERNUM'],
auth: [
[
'method' => 'ticket',
'type' => 'dynamic',
'authenticator' => 'testing',
'authenticator-realm' => 'realm1',
'realms' => ['realm1']
],
[
'method' => 'anonymous',
'type' => 'static',
'role' => 'auth'
]
],
);
$wamp = new Wamp($transportConfig, $adapter);

Expand Down
37 changes: 37 additions & 0 deletions src/Auth/AbstractAuthenticator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace Octamp\Wamp\Auth;

use Octamp\Wamp\Session\Session;
use Thruway\Message\HelloMessage;

abstract class AbstractAuthenticator implements AuthenticatorInterface
{
protected array $realms;

public function __construct(protected array $config)
{
$this->realms = $this->config['realms'] ?? [];
$this->init();
}

protected function init(): void
{
// overwrite this method for custom implementation
}

public function getRealms(): array
{
return $this->realms;
}

public function supportRealm(string $realmName): bool
{
return empty($this->realms) || in_array('*', $this->realms) || in_array($realmName, $this->realms);
}

public function canAuthenticate(Session $session, HelloMessage $message, array $methods): bool
{
return in_array($this->getMethod(), $methods) && $this->supportRealm($session->getRealm()->name);
}
}
97 changes: 97 additions & 0 deletions src/Auth/AbstractDynamicAuthenticator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

namespace Octamp\Wamp\Auth;

use Octamp\Wamp\Connection\WithEventDispatcherInterface;
use Octamp\Wamp\Helper\IDHelper;
use Octamp\Wamp\Promise\Deferred;
use Octamp\Wamp\Promise\PromiseInterface;
use Octamp\Wamp\Realm\RealmManager;
use Octamp\Wamp\Session\Event\MessageEvent;
use Thruway\Message\CallMessage;
use Thruway\Message\HelloMessage;
use Thruway\Message\Message;
use Thruway\Message\ResultMessage;

abstract class AbstractDynamicAuthenticator extends AbstractAuthenticator implements WithRealmManagerInterface
{
protected ?RealmManager $realmManager;

protected function sendMessageToAuthenticator(HelloMessage $message, array $details = []): PromiseInterface
{
$helloDetails = $message->getDetails();
$args = [
'authmethod' => $this->getMethod(),
];
if ($helloDetails->authid) {
$args['authid'] = $helloDetails->authid;
}
if (isset($helloDetails->authextra)) {
$args['authextra'] = $helloDetails->authextra;
}

$procedureName = $this->config['authenticator'];
$realm = $this->realmManager->getRealm($this->config['authenticator-realm']);
$realmSession = $realm->getMetaSession();
$requestId = IDHelper::incrementSessionWampID($realmSession);

$callMessage = new CallMessage($requestId, [], $procedureName, [
$realm->name,
$args['authid'] ?? null,
array_merge($args, $details),
]);

$deferred = new Deferred();

$connection = $realmSession->getTransport()->getConnection();
if ($connection instanceof WithEventDispatcherInterface) {
$connection->once('Message:' . Message::MSG_CALL . ':' . $callMessage->getRequestId(), function (MessageEvent $event): void {
$this->realmManager->dispatch($event->session, $event->message);
});
$connection->once(
'Message:' . Message::MSG_RESULT . ':' . $callMessage->getRequestId(),
function (MessageEvent $event) use ($connection, $callMessage, $deferred): void {
$connection->removeListenersForEvent('Message:' . Message::MSG_ERROR . ':' .$callMessage->getRequestId());
/** @var ResultMessage $message */
$message = $event->message;
$data = $message->getArguments();
if (empty($data)) {
$deferred->reject([]);
return;
}

$result = $data[0];
$success = $result['status'] ?? true;

if (!$success) {
$deferred->reject($result);
} else {
$deferred->resolve($result);
}
}
);
$connection->once(
'Message:' . Message::MSG_ERROR . ':' . $callMessage->getRequestId(),
function (MessageEvent $event) use ($connection, $callMessage, $deferred): void {
$connection->removeListenersForEvent('Message:' . Message::MSG_RESULT . ':' .$callMessage->getRequestId());
/** @var ErrorMessage $message */
$message = $event->message;

$deferred->resolve([
'error_uri' => $message->getErrorURI(),
'error_details' => $message->getDetails(),
]);
}
);
}

$realmSession->sendMessage($callMessage);

return $deferred->promise();
}

public function setRealmManager(RealmManager $realmManager): void
{
$this->realmManager = $realmManager;
}
}
64 changes: 64 additions & 0 deletions src/Auth/AnonymousDynamicAuthenticator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

namespace Octamp\Wamp\Auth;

use Octamp\Wamp\Promise\Promise;
use Octamp\Wamp\Promise\PromiseInterface;
use Octamp\Wamp\Realm\RealmManager;
use Octamp\Wamp\Session\Session;
use Thruway\Message\AuthenticateMessage;
use Thruway\Message\HelloMessage;

class AnonymousDynamicAuthenticator extends AbstractDynamicAuthenticator
{
protected ?RealmManager $realmManager;

public function processHello(Session $session, HelloMessage $message): PromiseInterface
{
$promise = $this->sendMessageToAuthenticator($message, []);
return $promise->then(function ($result) {
$authDetails = [];
if (isset($result['authid'])) {
$authDetails['authid'] = $result['authid'];
}
return [
'status' => AuthManager::STATUS_NO_CHALLENGE,
'auth_details' => $authDetails,
'verify_details' => $result,
'challenge_details' => [
'challenge_method' => $this->getMethod(),
],
];
}, function ($result) {
$response = [
'status' => AuthManager::STATUS_FAILURE,
];
if (isset($result['error_uri'])) {
$response['error_uri'] = $result['error_uri'];
}

if (isset($result['error_details'])) {
$response['error_details'] = $result['error_details'];
}

return $response;
});
}

public function processAuthenticate(Session $session, AuthenticateMessage $message): PromiseInterface
{
return new Promise(function (callable $resolve) {
$resolve(['status' => AuthManager::STATUS_SUCCESS]);
});
}

public function getMethod(): string
{
return 'anonymous';
}

public function setRealmManager(RealmManager $realmManager): void
{
$this->realmManager = $realmManager;
}
}
36 changes: 36 additions & 0 deletions src/Auth/AnonymousStaticAuthenticator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace Octamp\Wamp\Auth;

use Octamp\Wamp\Promise\Promise;
use Octamp\Wamp\Promise\PromiseInterface;
use Octamp\Wamp\Session\Session;
use Thruway\Message\AuthenticateMessage;
use Thruway\Message\HelloMessage;

class AnonymousStaticAuthenticator extends AbstractAuthenticator
{
public function processHello(Session $session, HelloMessage $message): PromiseInterface
{
return new Promise(function (callable $resolve) {
$resolve(['status' => AuthManager::STATUS_NO_CHALLENGE, 'auth_details' => [
'authid' => $this->config['authid'] ?? 'anonymous',
'authrole' => $this->config['role'] ?? 'anonymous',
]]);
});
}

public function getMethod(): string
{
return 'anonymous';
}

public function processAuthenticate(Session $session, AuthenticateMessage $message): PromiseInterface
{
return new Promise(function (callable $resolve) {
$resolve(['status' => AuthManager::STATUS_SUCCESS]);
});
}
}
Loading

0 comments on commit 8beb254

Please sign in to comment.