Improved jwt logic
* No longer stores full token, but only payload.
This commit is contained in:
		
							
								
								
									
										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,17 +88,13 @@ 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'])) {
 | 
					                throw new SecurityException(
 | 
				
			||||||
                $subscribeClaims = $claims['mercure']['subscribe'];
 | 
					                    message: "Insufficient permissions for subscribe", 
 | 
				
			||||||
                if (!$this->checkTopicClaims($topics, $subscribeClaims)) {
 | 
					                    code: SecurityException::ERR_NO_PERMISSION
 | 
				
			||||||
                    throw new SecurityException(
 | 
					                );
 | 
				
			||||||
                        message: "Insufficient permissions for subscribe", 
 | 
					 | 
				
			||||||
                        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
 | 
				
			||||||
@@ -153,18 +149,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.publish');
 | 
				
			||||||
            $claims = $tok->claims->getAll();
 | 
					            // check topic against publishClaims
 | 
				
			||||||
            if (isset($claims['mercure']['publish'])) {
 | 
					            if (!$this->checkTopicClaims($data['topic']??[], $claims)) {
 | 
				
			||||||
                $publishClaims = $claims['mercure']['publish'];
 | 
					                throw new SecurityException(
 | 
				
			||||||
                // check topic against publishClaims
 | 
					                    message: "Insufficient permissions for publish", 
 | 
				
			||||||
                if (!$this->checkTopicClaims($data['topic']??[], $publishClaims)) {
 | 
					                    code: SecurityException::ERR_NO_PERMISSION
 | 
				
			||||||
                    throw new SecurityException(
 | 
					                );
 | 
				
			||||||
                        message: "Insufficient permissions for publish", 
 | 
					 | 
				
			||||||
                        code: SecurityException::ERR_NO_PERMISSION
 | 
					 | 
				
			||||||
                    );
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            // reject if access denied
 | 
					            // reject if access denied
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user