Skip to content

Commit baada3d

Browse files
authored
Add jwt subscription (#45)
1 parent 67ab273 commit baada3d

File tree

4 files changed

+269
-0
lines changed

4 files changed

+269
-0
lines changed

Service/Credentials/CredentialsGenerator.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Fresh\CentrifugoBundle\Token\JwtPayload;
1717
use Fresh\CentrifugoBundle\Token\JwtPayloadForChannel;
1818
use Fresh\CentrifugoBundle\Token\JwtPayloadForPrivateChannel;
19+
use Fresh\CentrifugoBundle\Token\JwtSubscriptionPayload;
1920
use Fresh\CentrifugoBundle\User\CentrifugoUserInterface;
2021
use Fresh\CentrifugoBundle\User\CentrifugoUserMetaInterface;
2122
use Fresh\DateTime\DateTimeHelper;
@@ -80,6 +81,29 @@ public function generateJwtToken(string $subject, array $info = [], array $meta
8081
return $this->jwtGenerator->generateToken($jwtPayload);
8182
}
8283

84+
/**
85+
* @param string $subject
86+
* @param string $channel
87+
* @param array $info
88+
* @param array $meta
89+
* @param string|null $base64info
90+
*
91+
* @return string
92+
*/
93+
public function generateJwtSubscriptionToken(string $subject, string $channel, array $info = [], array $meta = [], ?string $base64info = null): string
94+
{
95+
$jwtPayload = new JwtSubscriptionPayload(
96+
subject: $subject,
97+
channel: $channel,
98+
info: $info,
99+
meta: $meta,
100+
expirationTime: $this->getExpirationTime(),
101+
base64info: $base64info,
102+
);
103+
104+
return $this->jwtGenerator->generateToken($jwtPayload);
105+
}
106+
83107
/**
84108
* @param string|null $base64info
85109
* @param array $channels

Tests/Service/Credentials/CredentialsGeneratorTest.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Fresh\CentrifugoBundle\Token\JwtPayload;
1818
use Fresh\CentrifugoBundle\Token\JwtPayloadForChannel;
1919
use Fresh\CentrifugoBundle\Token\JwtPayloadForPrivateChannel;
20+
use Fresh\CentrifugoBundle\Token\JwtSubscriptionPayload;
2021
use Fresh\CentrifugoBundle\User\CentrifugoUserInterface;
2122
use Fresh\CentrifugoBundle\User\CentrifugoUserMetaInterface;
2223
use Fresh\DateTime\DateTimeHelper;
@@ -132,6 +133,44 @@ public function generateJwtToken(): void
132133
);
133134
}
134135

136+
#[Test]
137+
public function generateJwtSubscriptionToken(): void
138+
{
139+
$this->dateTimeHelper
140+
->expects($this->once())
141+
->method('getCurrentDatetimeUtc')
142+
->willReturn(new \DateTime('2000-02-02 00:00:00', new \DateTimeZone('UTC')))
143+
;
144+
145+
$this->jwtGenerator
146+
->expects($this->once())
147+
->method('generateToken')
148+
->with($this->callback(static function (JwtSubscriptionPayload $jwtSubscriptionPayload) {
149+
return 'spiderman' === $jwtSubscriptionPayload->getSubject()
150+
&& 'channel' === $jwtSubscriptionPayload->getChannel()
151+
&& ['name' => 'Peter Parker', 'email' => 'spiderman@marvel.com'] === $jwtSubscriptionPayload->getInfo()
152+
&& 949449610 === $jwtSubscriptionPayload->getExpirationTime() // 2000-02-02 00:00:10
153+
&& 'qwerty' === $jwtSubscriptionPayload->getBase64Info()
154+
;
155+
}))
156+
->willReturn('test2')
157+
;
158+
159+
$this->assertEquals(
160+
'test2',
161+
$this->credentialsGenerator->generateJwtSubscriptionToken(
162+
subject: 'spiderman',
163+
channel: 'channel',
164+
info: [
165+
'name' => 'Peter Parker',
166+
'email' => 'spiderman@marvel.com',
167+
],
168+
meta: [],
169+
base64info: 'qwerty',
170+
)
171+
);
172+
}
173+
135174
#[Test]
136175
public function generateJwtTokenForAnonymous(): void
137176
{
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<?php
2+
/*
3+
* This file is part of the FreshCentrifugoBundle.
4+
*
5+
* (c) Artem Henvald <genvaldartem@gmail.com>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
11+
declare(strict_types=1);
12+
13+
namespace Fresh\CentrifugoBundle\Tests\Token;
14+
15+
use Fresh\CentrifugoBundle\Token\AbstractJwtPayload;
16+
use Fresh\CentrifugoBundle\Token\JwtSubscriptionPayload;
17+
use PHPUnit\Framework\Attributes\Test;
18+
use PHPUnit\Framework\TestCase;
19+
20+
/**
21+
* JwtSubscriptionPayload.
22+
*
23+
* @author Artem Henvald <genvaldartem@gmail.com>
24+
*/
25+
final class JwtSubscriptionPayloadTest extends TestCase
26+
{
27+
#[Test]
28+
public function constructor(): void
29+
{
30+
$jwtPayload = new JwtSubscriptionPayload(
31+
'spiderman',
32+
'channel',
33+
[
34+
'name' => 'Peter Parker',
35+
'email' => 'spiderman@marvel.com',
36+
],
37+
[
38+
'foo' => 'bar',
39+
],
40+
123,
41+
'test',
42+
);
43+
44+
$this->assertInstanceOf(AbstractJwtPayload::class, $jwtPayload);
45+
$this->assertSame('spiderman', $jwtPayload->getSubject());
46+
$this->assertSame('channel', $jwtPayload->getChannel());
47+
$this->assertSame(
48+
[
49+
'name' => 'Peter Parker',
50+
'email' => 'spiderman@marvel.com',
51+
],
52+
$jwtPayload->getInfo(),
53+
);
54+
$this->assertSame(
55+
[
56+
'foo' => 'bar',
57+
],
58+
$jwtPayload->getMeta(),
59+
);
60+
$this->assertSame(123, $jwtPayload->getExpirationTime());
61+
$this->assertSame('test', $jwtPayload->getBase64Info());
62+
}
63+
64+
#[Test]
65+
public function getPayloadDataWithAllClaims(): void
66+
{
67+
$jwtPayload = new JwtSubscriptionPayload(
68+
'spiderman',
69+
'channel',
70+
[
71+
'name' => 'Peter Parker',
72+
'email' => 'spiderman@marvel.com',
73+
],
74+
[
75+
'foo' => 'bar',
76+
],
77+
123,
78+
'test',
79+
);
80+
81+
$this->assertEquals(
82+
[
83+
'sub' => 'spiderman',
84+
'channel' => 'channel',
85+
'info' => [
86+
'name' => 'Peter Parker',
87+
'email' => 'spiderman@marvel.com',
88+
],
89+
'meta' => [
90+
'foo' => 'bar',
91+
],
92+
'exp' => 123,
93+
'b64info' => 'test',
94+
],
95+
$jwtPayload->getPayloadData(),
96+
);
97+
}
98+
99+
#[Test]
100+
public function getPayloadDataWithOnlyRequiredClaims(): void
101+
{
102+
$jwtPayload = new JwtSubscriptionPayload(
103+
'spiderman',
104+
'channel',
105+
);
106+
107+
$this->assertEquals(
108+
[
109+
'sub' => 'spiderman',
110+
'channel' => 'channel',
111+
],
112+
$jwtPayload->getPayloadData(),
113+
);
114+
}
115+
}

Token/JwtSubscriptionPayload.php

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
/*
3+
* This file is part of the FreshCentrifugoBundle.
4+
*
5+
* (c) Artem Henvald <genvaldartem@gmail.com>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
11+
declare(strict_types=1);
12+
13+
namespace Fresh\CentrifugoBundle\Token;
14+
15+
use JetBrains\PhpStorm\ArrayShape;
16+
17+
/**
18+
* JwtSubscriptionPayload.
19+
*
20+
* @see https://centrifugal.dev/docs/server/channel_token_auth
21+
*
22+
* @author Artem Henvald <genvaldartem@gmail.com>
23+
*/
24+
final class JwtSubscriptionPayload extends AbstractJwtPayload
25+
{
26+
/**
27+
* @param string $subject
28+
* @param string $channel
29+
* @param array $info
30+
* @param array $meta
31+
* @param int|null $expirationTime
32+
* @param string|null $base64info
33+
*/
34+
public function __construct(private readonly string $subject, private readonly string $channel, array $info = [], array $meta = [], ?int $expirationTime = null, ?string $base64info = null)
35+
{
36+
parent::__construct($info, $meta, $expirationTime, $base64info);
37+
}
38+
39+
/**
40+
* @return string
41+
*/
42+
public function getSubject(): string
43+
{
44+
return $this->subject;
45+
}
46+
47+
/**
48+
* @return string
49+
*/
50+
public function getChannel(): string
51+
{
52+
return $this->channel;
53+
}
54+
55+
/**
56+
* @return array
57+
*/
58+
#[ArrayShape([
59+
'sub' => 'string',
60+
'channel' => 'string',
61+
'b64info' => 'null|string',
62+
'info' => 'array',
63+
'meta' => 'array',
64+
'exp' => 'int|null',
65+
])]
66+
public function getPayloadData(): array
67+
{
68+
$data = [
69+
'sub' => $this->getSubject(),
70+
'channel' => $this->getChannel(),
71+
];
72+
73+
if (null !== $this->getExpirationTime()) {
74+
$data['exp'] = $this->getExpirationTime();
75+
}
76+
77+
if (!empty($this->getInfo())) {
78+
$data['info'] = $this->getInfo();
79+
}
80+
81+
if (!empty($this->getMeta())) {
82+
$data['meta'] = $this->getMeta();
83+
}
84+
85+
if (null !== $this->getBase64Info()) {
86+
$data['b64info'] = $this->getBase64Info();
87+
}
88+
89+
return $data;
90+
}
91+
}

0 commit comments

Comments
 (0)