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

Amazon Cognito integration #2028

Merged
merged 8 commits into from
Dec 9, 2024
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
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 <opensource@hardware.info>
*
* 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 <altynbek.usenov@gmail.com>
*/
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 <opensource@hardware.info>
*
* 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": "baz@example.com"
}
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('baz@example.com', $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
);
}
}
Loading