Skip to content

Commit

Permalink
Amazon Cognito integration (#2028)
Browse files Browse the repository at this point in the history
* Add Amazon Cognito

* Add a link to docs

* Remove not needed option

* Remove default not needed

* Fix the test and PSR

* Fix tests

* Tests fix 2

---------

Co-authored-by: Al <[email protected]>
  • Loading branch information
latysh and Al authored Dec 9, 2024
1 parent 250856c commit 381d2ed
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ file in this bundle. Read the documentation for version:
This bundle contains support for 58 different providers:
* 37signals,
* Amazon,
* Amazon Cognito
* Apple,
* Asana,
* Auth0,
Expand Down
1 change: 1 addition & 0 deletions docs/2-configuring_resource_owners.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ hwi_oauth:
- [37signals](resource_owners/37signals.md)
- [Asana](resource_owners/asana.md)
- [Amazon](resource_owners/amazon.md)
- [Amazon Cognito](resource_owners/amazon_cognito.md)
- [Apple](resource_owners/apple.md)
- [Auth0](resource_owners/auth0.md)
- [Azure](resource_owners/azure.md)
Expand Down
31 changes: 31 additions & 0 deletions docs/resource_owners/amazon_cognito.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
Step 2x: Setup Amazon Cognito
=====================
1. First you will need to creat a user pool on Amazon Cognito https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-next-steps.html.
2. Next, we need to create an app client for this user pool so that we can use Cognito’s OAuth 2.0 service. Make sure to take note of the `client_id` and `client_secret` as we will need them later. https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-client-apps.html
3. Add a callback URL `{HOST}/security/cognito/check`.
4. You will also need cognito `domain` and `region` (found in Amazon Cognito)

Next configure a resource owner of type `amazon_cognito` with appropriate
`client_id`, `client_secret` and `scope`. Refer to the Amazon documentation
for the available scopes.

``` yaml
# config/packages/hwi_oauth.yaml

hwi_oauth:
resource_owners:
any_name:
type: amazon_cognito
client_id: <client_id>
client_secret: <client_secret>
scope: "email openid" #needs to be enabled in cognito (profile, phone)
options:
region: <pool_region>
domain: <pool_domain>
```
When you're done. Continue by configuring the security layer or go back to
setup more resource owners.
- [Step 2: Configuring resource owners (Facebook, GitHub, Google, Windows Live and others](../2-configuring_resource_owners.md)
- [Step 3: Configuring the security layer](../3-configuring_the_security_layer.md).
61 changes: 61 additions & 0 deletions src/OAuth/ResourceOwner/AmazonCognitoResourceOwner.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

/*
* This file is part of the HWIOAuthBundle package.
*
* (c) Hardware Info <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace HWI\Bundle\OAuthBundle\OAuth\ResourceOwner;

use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;

/**
* @author Latysh <[email protected]>
*/
final class AmazonCognitoResourceOwner extends GenericOAuth2ResourceOwner
{
public const TYPE = 'amazon_cognito';

protected array $paths = [
'identifier' => 'sub',
'firstname' => 'given_name',
'lastname' => 'family_name',
'email' => 'email',
'nickname' => 'nickname',
'realname' => 'name',
];

protected function configureOptions(OptionsResolver $resolver)
{
parent::configureOptions($resolver);

$resolver->setDefaults([
'authorization_url' => '{base_url}/oauth2/authorize',
'access_token_url' => '{base_url}/oauth2/token',
'revoke_token_url' => '{base_url}/oauth2/revoke',
'infos_url' => '{base_url}/oauth2/userInfo',
]);

$resolver->setRequired([
'region',
'domain',
]);

$normalizer = function (Options $options, $value) {
$baseUrl = \sprintf('https://%s.auth.%s.amazoncognito.com', $options['domain'], $options['region']);

return str_replace('{base_url}', $baseUrl, $value);
};

$resolver
->setNormalizer('authorization_url', $normalizer)
->setNormalizer('access_token_url', $normalizer)
->setNormalizer('revoke_token_url', $normalizer)
->setNormalizer('infos_url', $normalizer);
}
}
91 changes: 91 additions & 0 deletions tests/OAuth/ResourceOwner/AmazonCognitoResourceOwnerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

/*
* This file is part of the HWIOAuthBundle package.
*
* (c) Hardware Info <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace HWI\Bundle\OAuthBundle\Tests\OAuth\ResourceOwner;

use HWI\Bundle\OAuthBundle\OAuth\ResourceOwner\AmazonCognitoResourceOwner;
use HWI\Bundle\OAuthBundle\OAuth\ResourceOwnerInterface;
use HWI\Bundle\OAuthBundle\OAuth\Response\AbstractUserResponse;
use HWI\Bundle\OAuthBundle\Test\OAuth\ResourceOwner\GenericOAuth2ResourceOwnerTestCase;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\HttpUtils;

final class AmazonCognitoResourceOwnerTest extends GenericOAuth2ResourceOwnerTestCase
{
protected string $resourceOwnerClass = AmazonCognitoResourceOwner::class;
protected string $userResponse = <<<json
{
"sub": "111",
"name": "bar",
"email": "[email protected]"
}
json;

protected array $paths = [
'identifier' => 'user_id',
'nickname' => 'name',
'realname' => 'name',
'email' => 'email',
];

public function testGetUserInformation(): void
{
$resourceOwner = $this->createResourceOwner(
[],
[],
[
$this->createMockResponse($this->userResponse, 'application/json; charset=utf-8'),
]
);

/**
* @var AbstractUserResponse
*/
$userResponse = $resourceOwner->getUserInformation(['access_token' => 'token']);

$this->assertEquals('[email protected]', $userResponse->getEmail());
$this->assertEquals('bar', $userResponse->getRealName());
$this->assertNull($userResponse->getFirstName());
$this->assertNull($userResponse->getProfilePicture());
$this->assertEquals('token', $userResponse->getAccessToken());
}

public function testGetUserInformationFailure(): void
{
$this->expectException(AuthenticationException::class);

$resourceOwner = $this->createResourceOwner(
[],
[],
[
$this->createMockResponse('invalid', 'application/json; charset=utf-8', 401),
]
);

$resourceOwner->getUserInformation($this->tokenData);
}

protected function setUpResourceOwner(string $name, HttpUtils $httpUtils, array $options, array $responses): ResourceOwnerInterface
{
return parent::setUpResourceOwner(
$name,
$httpUtils,
array_merge(
[
'domain' => 'test.com',
'region' => 'us-west-2',
],
$options
),
$responses
);
}
}

0 comments on commit 381d2ed

Please sign in to comment.