Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add support for Authenticated Push #2354

Merged
merged 2 commits into from
Oct 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Core/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"require": {
"php": ">=5.5",
"rize/uri-template": "~0.3",
"google/auth": "^1.5.1",
"google/auth": "^1.6",
"guzzlehttp/guzzle": "^5.3|^6.0",
"guzzlehttp/promises": "^1.3",
"guzzlehttp/psr7": "^1.2",
Expand Down
59 changes: 51 additions & 8 deletions PubSub/src/Subscription.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,25 @@
* 'my-new-topic'
* );
* ```
*
* ```
* // Consuming messages received via push with JWT Authentication.
* use Google\Auth\AccessToken;
*
* // Remove the `Bearer ` prefix from the token.
* // If using another request manager such as Symfony HttpFoundation,
* // use `Authorization` as the header name, e.g. `$request->headers->get('Authorization')`.
* $jwt = explode(' ', $_SERVER['HTTP_AUTHORIZATION'])[1];
*
* // Using the Access Token utility requires installation of the `phpseclib/phpseclib` dependency at version 2.
* $accessTokenUtility = new AccessToken();
* $payload = $accessTokenUtility->verify($jwt);
* if (!$payload) {
* throw new \RuntimeException('Could not verify token!');
* }
*
* echo 'Authenticated using ' . $payload['email'];
* ```
*/
class Subscription
{
Expand Down Expand Up @@ -185,15 +204,25 @@ public function name()
* @param array $options [optional] {
* Configuration Options
*
* For information regarding the push configuration settings, see
* [PushConfig](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions#PushConfig).
*
* @type string $pushConfig.pushEndpoint A URL locating the endpoint to which
* messages should be pushed. For example, a Webhook endpoint
* might use "https://example.com/push".
* @type array $pushConfig.attributes Endpoint configuration attributes.
* @type array $pushConfig.oidcToken Contains information needed for generating
* an OpenIDConnect token.
* @type array $pushConfig.oidcToken If specified, Pub/Sub will generate
* and attach an OIDC JWT token as an `Authorization` header in
* the HTTP request for every pushed message.
* @type string $pushConfig.oidcToken.serviceAccountEmail Service
* account email to be used for generating the OIDC token. The
* caller (for `subscriptions.create`, `UpdateSubscription`, and
* `subscriptions.modifyPushConfig` RPCs) must have the
* `iam.serviceAccounts.actAs` permission for the service account.
* @type string $pushConfig.oidcToken.audience Audience to be used when
* generating OIDC token. The audience claim identifies the
* recipients that the JWT is intended for. The audience value is
* a single case-sensitive string. Having multiple values (array)
* for the audience field is not supported. More info about the
* OIDC JWT token audience here: https://tools.ietf.org/html/rfc7519#section-4.1.3
* Note: if not specified, the Push endpoint URL will be used.
* @type int $ackDeadlineSeconds The maximum time after a subscriber
* receives a message before the subscriber should acknowledge the
* message.
Expand Down Expand Up @@ -276,16 +305,30 @@ public function create(array $options = [])
* ]);
* ```
*
* @see https://cloud.google.com/pubsub/docs/reference/rest/v1/UpdateSubscriptionRequest UpdateSubscriptionRequest
*
* @param array $subscription {
* The Subscription data.
*
* For information regarding the push configuration settings, see
* [PushConfig](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions#PushConfig).
*
* @type string $pushConfig.pushEndpoint A URL locating the endpoint to which
* messages should be pushed. For example, a Webhook endpoint
* might use "https://example.com/push".
* @type array $pushConfig.attributes Endpoint configuration attributes.
* @type array $pushConfig.oidcToken If specified, Pub/Sub will generate
* and attach an OIDC JWT token as an `Authorization` header in
* the HTTP request for every pushed message.
* @type string $pushConfig.oidcToken.serviceAccountEmail Service
* account email to be used for generating the OIDC token. The
* caller (for `subscriptions.create`, `UpdateSubscription`, and
* `subscriptions.modifyPushConfig` RPCs) must have the
* `iam.serviceAccounts.actAs` permission for the service account.
* @type string $pushConfig.oidcToken.audience Audience to be used when
* generating OIDC token. The audience claim identifies the
* recipients that the JWT is intended for. The audience value is
* a single case-sensitive string. Having multiple values (array)
* for the audience field is not supported. More info about the
* OIDC JWT token audience here: https://tools.ietf.org/html/rfc7519#section-4.1.3
* Note: if not specified, the Push endpoint URL will be used.
* @type int $ackDeadlineSeconds The maximum time after a subscriber
* receives a message before the subscriber should acknowledge the
* message.
Expand Down
40 changes: 40 additions & 0 deletions PubSub/tests/Snippet/SubscriptionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

namespace Google\Cloud\PubSub\Tests\Snippet;

use Google\Auth\AccessToken;
use Google\Cloud\Core\Iam\Iam;
use Google\Cloud\Core\Testing\Snippet\SnippetTestCase;
use Google\Cloud\Core\Testing\TestHelpers;
Expand Down Expand Up @@ -71,6 +72,45 @@ public function testClassThroughPubSubClient()
$this->assertEquals(self::SUBSCRIPTION, $res->returnVal()->name());
}

public function testAuthenticatedPush()
{
$authToken = 'foobar';
$email = '[email protected]';
$token = $this->prophesize(AccessToken::class);
$token->verify($authToken)
->shouldBeCalled()
->willReturn([
'email' => $email
]);

$snippet = $this->snippetFromClass(Subscription::class, 2);
$snippet->replace('$accessTokenUtility = new AccessToken();', '');
$snippet->addLocal('accessTokenUtility', $token->reveal());
$_SERVER['HTTP_AUTHORIZATION'] = 'Bearer ' . $authToken;

$res = $snippet->invoke();
$this->assertEquals('Authenticated using ' . $email, $res->output());
}

/**
* @expectedException \RuntimeException
*/
public function testAuthenticatedPushFails()
{
$authToken = 'foobar';
$token = $this->prophesize(AccessToken::class);
$token->verify($authToken)
->shouldBeCalled()
->willReturn(false);

$snippet = $this->snippetFromClass(Subscription::class, 2);
$snippet->replace('$accessTokenUtility = new AccessToken();', '');
$snippet->addLocal('accessTokenUtility', $token->reveal());
$_SERVER['HTTP_AUTHORIZATION'] = 'Bearer ' . $authToken;

$res = $snippet->invoke();
}

public function testName()
{
$snippet = $this->snippetFromMethod(Subscription::class, 'name');
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"ramsey/uuid": "~3",
"google/gax": "^1.1",
"google/common-protos": "^1.0",
"google/auth": "^1.5.1",
"google/auth": "^1.6",
"google/crc32": "^0.1.0"
},
"require-dev": {
Expand Down