Skip to content

Commit 5af9786

Browse files
committed
Implement wrapper method of issue_stateless_channel_token
1 parent b0eeab2 commit 5af9786

3 files changed

Lines changed: 164 additions & 1 deletion

File tree

src/clients/channel-access-token/lib/Api/ChannelAccessTokenApi.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2558,4 +2558,44 @@ protected function createHttpClientOption()
25582558

25592559
return $options;
25602560
}
2561+
/**
2562+
* Issue a stateless channel access token by JWT assertion.
2563+
*
2564+
* @param string $clientAssertion A JSON Web Token the client needs to create and sign with the private key of the Assertion Signing Key.
2565+
* @param string $contentType The value for the Content-Type header.
2566+
*
2567+
* @throws \LINE\Clients\ChannelAccessToken\ApiException on non-2xx response or if the response body is not in the expected format
2568+
* @throws \InvalidArgumentException
2569+
* @return \LINE\Clients\ChannelAccessToken\Model\IssueStatelessChannelAccessTokenResponse
2570+
*/
2571+
public function issueStatelessChannelTokenByJWTAssertion($clientAssertion, string $contentType = self::contentTypes['issueStatelessChannelToken'][0])
2572+
{
2573+
return $this->issueStatelessChannelToken(
2574+
grantType: 'client_credentials',
2575+
clientAssertionType: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
2576+
clientAssertion: $clientAssertion,
2577+
contentType: $contentType,
2578+
);
2579+
}
2580+
2581+
/**
2582+
* Issue a stateless channel access token by client secret.
2583+
*
2584+
* @param string $clientId Channel ID.
2585+
* @param string $clientSecret Channel secret.
2586+
* @param string $contentType The value for the Content-Type header.
2587+
*
2588+
* @throws \LINE\Clients\ChannelAccessToken\ApiException on non-2xx response or if the response body is not in the expected format
2589+
* @throws \InvalidArgumentException
2590+
* @return \LINE\Clients\ChannelAccessToken\Model\IssueStatelessChannelAccessTokenResponse
2591+
*/
2592+
public function issueStatelessChannelTokenByClientSecret($clientId, $clientSecret, string $contentType = self::contentTypes['issueStatelessChannelToken'][0])
2593+
{
2594+
return $this->issueStatelessChannelToken(
2595+
grantType: 'client_credentials',
2596+
clientId: $clientId,
2597+
clientSecret: $clientSecret,
2598+
contentType: $contentType,
2599+
);
2600+
}
25612601
}

test/clients/channel-access-token/Api/ChannelAccessTokenApiTest.php

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,68 @@ public function testIssueStatelessChannelToken(): void
5656
$this->assertEquals(30, $response->getExpiresIn());
5757
$this->assertEquals('Bearer', $response->getTokenType());
5858
}
59+
60+
public function testIssueStatelessChannelTokenByJWTAssertion(): void
61+
{
62+
$client = Mockery::mock(ClientInterface::class);
63+
$client->shouldReceive('send')
64+
->with(
65+
Mockery::on(function (Request $request) {
66+
$this->assertEquals('POST', $request->getMethod());
67+
$this->assertEquals('https://api.line.me/oauth2/v3/token', (string)$request->getUri());
68+
$body = (string)$request->getBody();
69+
parse_str($body, $params);
70+
$this->assertEquals('client_credentials', $params['grant_type']);
71+
$this->assertEquals('urn:ietf:params:oauth:client-assertion-type:jwt-bearer', $params['client_assertion_type']);
72+
$this->assertEquals('jwtAssertionToken', $params['client_assertion']);
73+
$this->assertArrayNotHasKey('client_id', $params);
74+
$this->assertArrayNotHasKey('client_secret', $params);
75+
return true;
76+
}),
77+
[]
78+
)
79+
->once()
80+
->andReturn(new Response(
81+
status: 200,
82+
headers: [],
83+
body: json_encode(['access_token' => 'accessToken', 'expires_in' => 30, 'token_type' => 'Bearer']),
84+
));
85+
$api = new ChannelAccessTokenApi($client);
86+
$response = $api->issueStatelessChannelTokenByJWTAssertion(clientAssertion: "jwtAssertionToken");
87+
$this->assertEquals('accessToken', $response->getAccessToken());
88+
$this->assertEquals(30, $response->getExpiresIn());
89+
$this->assertEquals('Bearer', $response->getTokenType());
90+
}
91+
92+
public function testIssueStatelessChannelTokenByClientSecret(): void
93+
{
94+
$client = Mockery::mock(ClientInterface::class);
95+
$client->shouldReceive('send')
96+
->with(
97+
Mockery::on(function (Request $request) {
98+
$this->assertEquals('POST', $request->getMethod());
99+
$this->assertEquals('https://api.line.me/oauth2/v3/token', (string)$request->getUri());
100+
$body = (string)$request->getBody();
101+
parse_str($body, $params);
102+
$this->assertEquals('client_credentials', $params['grant_type']);
103+
$this->assertEquals('1234', $params['client_id']);
104+
$this->assertEquals('clientSecret', $params['client_secret']);
105+
$this->assertArrayNotHasKey('client_assertion_type', $params);
106+
$this->assertArrayNotHasKey('client_assertion', $params);
107+
return true;
108+
}),
109+
[]
110+
)
111+
->once()
112+
->andReturn(new Response(
113+
status: 200,
114+
headers: [],
115+
body: json_encode(['access_token' => 'accessToken', 'expires_in' => 30, 'token_type' => 'Bearer']),
116+
));
117+
$api = new ChannelAccessTokenApi($client);
118+
$response = $api->issueStatelessChannelTokenByClientSecret(clientId: "1234", clientSecret: "clientSecret");
119+
$this->assertEquals('accessToken', $response->getAccessToken());
120+
$this->assertEquals(30, $response->getExpiresIn());
121+
$this->assertEquals('Bearer', $response->getTokenType());
122+
}
59123
}

tools/patch-gen-oas-client.php

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,66 @@ function removeDiscriminatorType($filename)
4242
file_put_contents($filename, $content);
4343
}
4444

45+
function addStatelessChannelTokenWrappers()
46+
{
47+
$filename = __DIR__ . '/../src/clients/channel-access-token/lib/Api/ChannelAccessTokenApi.php';
48+
$content = file_get_contents($filename);
49+
if (str_contains($content, 'issueStatelessChannelTokenByJWTAssertion')) {
50+
return;
51+
}
52+
53+
$wrappers = <<<'WRAPPERS'
54+
55+
/**
56+
* Issue a stateless channel access token by JWT assertion.
57+
*
58+
* @param string $clientAssertion A JSON Web Token the client needs to create and sign with the private key of the Assertion Signing Key.
59+
* @param string $contentType The value for the Content-Type header.
60+
*
61+
* @throws \LINE\Clients\ChannelAccessToken\ApiException on non-2xx response or if the response body is not in the expected format
62+
* @throws \InvalidArgumentException
63+
* @return \LINE\Clients\ChannelAccessToken\Model\IssueStatelessChannelAccessTokenResponse
64+
*/
65+
public function issueStatelessChannelTokenByJWTAssertion($clientAssertion, string $contentType = self::contentTypes['issueStatelessChannelToken'][0])
66+
{
67+
return $this->issueStatelessChannelToken(
68+
grantType: 'client_credentials',
69+
clientAssertionType: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
70+
clientAssertion: $clientAssertion,
71+
contentType: $contentType,
72+
);
73+
}
74+
75+
/**
76+
* Issue a stateless channel access token by client secret.
77+
*
78+
* @param string $clientId Channel ID.
79+
* @param string $clientSecret Channel secret.
80+
* @param string $contentType The value for the Content-Type header.
81+
*
82+
* @throws \LINE\Clients\ChannelAccessToken\ApiException on non-2xx response or if the response body is not in the expected format
83+
* @throws \InvalidArgumentException
84+
* @return \LINE\Clients\ChannelAccessToken\Model\IssueStatelessChannelAccessTokenResponse
85+
*/
86+
public function issueStatelessChannelTokenByClientSecret($clientId, $clientSecret, string $contentType = self::contentTypes['issueStatelessChannelToken'][0])
87+
{
88+
return $this->issueStatelessChannelToken(
89+
grantType: 'client_credentials',
90+
clientId: $clientId,
91+
clientSecret: $clientSecret,
92+
contentType: $contentType,
93+
);
94+
}
95+
WRAPPERS;
96+
97+
// Insert before the closing brace of the class
98+
$content = preg_replace('/\n}\s*$/', $wrappers . "\n}\n", $content);
99+
file_put_contents($filename, $content);
100+
}
101+
45102
$recursive_directory_iterator = new \RecursiveDirectoryIterator(
46103
__DIR__ . '/../src/',
47-
\FilesystemIterator::SKIP_DOTS
104+
\FilesystemIterator::SKIP_DOTS
48105
| \FilesystemIterator::KEY_AS_PATHNAME
49106
| \FilesystemIterator::CURRENT_AS_FILEINFO
50107
);
@@ -56,3 +113,5 @@ function removeDiscriminatorType($filename)
56113
echo $filename;
57114
patchFile($filename);
58115
}
116+
117+
addStatelessChannelTokenWrappers();

0 commit comments

Comments
 (0)