Improved jwt logic
* No longer stores full token, but only payload.
This commit is contained in:
parent
99b5710c59
commit
0513ab0999
10
README.md
10
README.md
@ -34,24 +34,24 @@ $ ./mercureact.phar -c mercureact.conf
|
|||||||
|
|
||||||
## ToDos
|
## ToDos
|
||||||
|
|
||||||
* [ ] Read config from file
|
* [x] Read config from file
|
||||||
* [ ] Security Security Security
|
* [ ] Security Security Security
|
||||||
* [x] Check JWTs on connect
|
* [x] Check JWTs on connect
|
||||||
* [x] Check claims on subscribe and publish
|
* [x] Check claims on subscribe and publish
|
||||||
* [ ] WebSocket authentication
|
* [x] Extract JWT claims to request attributes, instead of JWTToken
|
||||||
* [ ] Extract JWT claims to request attributes, instead of JWTToken
|
|
||||||
* [x] Subscription/Topic manager
|
* [x] Subscription/Topic manager
|
||||||
* [x] Unify distribution
|
* [x] Unify distribution
|
||||||
* [ ] Enumerate subscriptions and topics
|
* [x] Enumerate subscriptions and topics
|
||||||
* [x] Publish events
|
* [x] Publish events
|
||||||
* [x] Server-Side Events distributor
|
* [x] Server-Side Events distributor
|
||||||
* [x] Distribute events over SSE
|
* [x] Distribute events over SSE
|
||||||
* [ ] WebSocket distributor
|
* [ ] WebSocket distributor
|
||||||
|
* [ ] WebSocket authentication
|
||||||
* [ ] Setup subscriptions
|
* [ ] Setup subscriptions
|
||||||
* [ ] Dynamic subscriptions
|
* [ ] Dynamic subscriptions
|
||||||
* [x] Distribute events over WS
|
* [x] Distribute events over WS
|
||||||
* [x] Break out HTTP middleware into classes
|
* [x] Break out HTTP middleware into classes
|
||||||
* [ ] HTTP middleware unittests
|
* [ ] HTTP middleware unittests
|
||||||
* [ ] Replay missed events based on event id
|
* [ ] Replay missed events based on event id
|
||||||
* [ ] Figure out how to determine last event IDs
|
* [x] Figure out how to determine last event IDs
|
||||||
* [ ] Metrics endpoint
|
* [ ] Metrics endpoint
|
||||||
|
@ -26,7 +26,12 @@ class SseSubscriber implements SubscriberInterface
|
|||||||
|
|
||||||
public function isAuthorized(): bool
|
public function isAuthorized(): bool
|
||||||
{
|
{
|
||||||
return $this->request->getAttribute('authorization') instanceof JWTToken;
|
return $this->request->getAttribute('authorized');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPayload(): array
|
||||||
|
{
|
||||||
|
return $this->request->getAttribute('mercure.payload')??[];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getId(): string
|
public function getId(): string
|
||||||
|
@ -69,7 +69,7 @@ class TopicManager
|
|||||||
'topic' => $topic->getTopic(),
|
'topic' => $topic->getTopic(),
|
||||||
'subscriber' => $sub->getId(),
|
'subscriber' => $sub->getId(),
|
||||||
'active' => true,
|
'active' => true,
|
||||||
'payload' => null, // TODO populate from mercure.payload in JWT
|
'payload' => $sub->getPayload(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,18 +88,14 @@ class MercureHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Grab the JWT token from the requests authorization attribute
|
// Grab the JWT token from the requests authorization attribute
|
||||||
$tok = $request->getAttribute('authorization');
|
if ($request->getAttribute('authorized')) {
|
||||||
if ($tok instanceof JWTToken) {
|
$claims = $request->getAttribute('mercure.subscribe');
|
||||||
$claims = $tok->claims->getAll();
|
if (!$this->checkTopicClaims($topics, $claims)) {
|
||||||
if (isset($claims['mercure']['subscribe'])) {
|
|
||||||
$subscribeClaims = $claims['mercure']['subscribe'];
|
|
||||||
if (!$this->checkTopicClaims($topics, $subscribeClaims)) {
|
|
||||||
throw new SecurityException(
|
throw new SecurityException(
|
||||||
message: "Insufficient permissions for subscribe",
|
message: "Insufficient permissions for subscribe",
|
||||||
code: SecurityException::ERR_NO_PERMISSION
|
code: SecurityException::ERR_NO_PERMISSION
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Disallow if we don't allow anonymous subscribers. Note that anonymous
|
// Disallow if we don't allow anonymous subscribers. Note that anonymous
|
||||||
// subscribers will not receive updates marked as private.
|
// subscribers will not receive updates marked as private.
|
||||||
@ -153,19 +149,15 @@ class MercureHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Grab the JWT token from the requests authorization attribute
|
// Grab the JWT token from the requests authorization attribute
|
||||||
$tok = $request->getAttribute('authorization');
|
if ($request->getAttribute('authorized')) {
|
||||||
if ($tok instanceof JWTToken) {
|
$claims = $request->getAttribute('mercure.publish');
|
||||||
$claims = $tok->claims->getAll();
|
|
||||||
if (isset($claims['mercure']['publish'])) {
|
|
||||||
$publishClaims = $claims['mercure']['publish'];
|
|
||||||
// check topic against publishClaims
|
// check topic against publishClaims
|
||||||
if (!$this->checkTopicClaims($data['topic']??[], $publishClaims)) {
|
if (!$this->checkTopicClaims($data['topic']??[], $claims)) {
|
||||||
throw new SecurityException(
|
throw new SecurityException(
|
||||||
message: "Insufficient permissions for publish",
|
message: "Insufficient permissions for publish",
|
||||||
code: SecurityException::ERR_NO_PERMISSION
|
code: SecurityException::ERR_NO_PERMISSION
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// reject if access denied
|
// reject if access denied
|
||||||
throw new SecurityException(
|
throw new SecurityException(
|
||||||
|
@ -61,11 +61,15 @@ class SecurityMiddleware
|
|||||||
code: SecurityException::ERR_ACCESS_DENIED
|
code: SecurityException::ERR_ACCESS_DENIED
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
$claims = $tok->claims->getAll()['mercure']??[];
|
||||||
return $request
|
return $request
|
||||||
->withAttribute('authorization', $tok);
|
->withAttribute('mercure.publish', $claims['publish']??[])
|
||||||
|
->withAttribute('mercure.subscribe', $claims['subscribe']??[])
|
||||||
|
->withAttribute('mercure.payload', $claims['payload']??[])
|
||||||
|
->withAttribute('authorized', true);
|
||||||
} else {
|
} else {
|
||||||
return $request
|
return $request
|
||||||
->withAttribute('authorization', null);
|
->withAttribute('authorized', false);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user