-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
added oauth2 documentation #182
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,340 @@ | ||
# Adding a OAuth2 authentication using `FOSOAuthServerBundle` | ||
|
||
> [OAuth](https://oauth.net/2/) is an open standard for authorization, commonly used as a way for Internet users to authorize websites or applications to access their information on other websites but without giving them the passwords.[1] This mechanism is used by companies such as Google, Facebook, Microsoft and Twitter to permit the users to share information about their accounts with third party applications or websites. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you remove the |
||
|
||
[Wikipedia](https://en.wikipedia.org/wiki/OAuth) | ||
|
||
API Platform allows to easily add a OAuth2-based authentication to your API using [FOSOAuthServerBundle](https://github.com/FriendsOfSymfony/FOSOAuthServerBundle). | ||
|
||
API Platform is fully working with [FOSOAuthServerBundle](https://github.com/FriendsOfSymfony/FOSOAuthServerBundle). | ||
|
||
This tutorial is based on [Getting Started With FOSOAuthServerBundle](https://github.com/FriendsOfSymfony/FOSOAuthServerBundle/blob/master/Resources/doc/index.md) and [Basic RESTful API with Symfony 2 + FOSRestBundle (JSON format only) + FOSUserBundle + FOSOauthServerBundle](https://gist.github.com/tjamps/11d617a4b318d65ca583) | ||
|
||
## Install FOSOauthServerBundle | ||
|
||
Install the bundle with composer: | ||
|
||
```bash | ||
composer require friendsofsymfony/oauth-server-bundle | ||
``` | ||
|
||
Enable the bundle in the kernel: | ||
|
||
```php | ||
<?php | ||
// app/AppKernel.php | ||
|
||
public function registerBundles() | ||
{ | ||
$bundles = array( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you use the short array syntax please? |
||
// ... | ||
new FOS\OAuthServerBundle\FOSOAuthServerBundle(), | ||
); | ||
} | ||
``` | ||
|
||
## Create oauth2 entites | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
Add all the following classes to your entities and run `php bin/console doctrine:schema:update --force`: | ||
|
||
`AppBundle/Entity/AccessToken.php` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We put the filename as a comment just after |
||
|
||
```php | ||
<?php | ||
|
||
namespace AppBundle\Entity; | ||
|
||
use FOS\OAuthServerBundle\Entity\AccessToken as BaseAccessToken; | ||
use Doctrine\ORM\Mapping as ORM; | ||
|
||
/** | ||
* @ORM\Entity | ||
*/ | ||
class AccessToken extends BaseAccessToken | ||
{ | ||
/** | ||
* @ORM\Id | ||
* @ORM\Column(type="integer") | ||
* @ORM\GeneratedValue(strategy="AUTO") | ||
*/ | ||
protected $id; | ||
|
||
/** | ||
* @ORM\ManyToOne(targetEntity="Client") | ||
* @ORM\JoinColumn(nullable=false) | ||
*/ | ||
protected $client; | ||
|
||
/** | ||
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User") | ||
*/ | ||
protected $user; | ||
} | ||
``` | ||
|
||
`AppBundle/Entity/AuthCode.php` | ||
|
||
```php | ||
<?php | ||
|
||
namespace AppBundle\Entity; | ||
|
||
use FOS\OAuthServerBundle\Entity\AuthCode as BaseAuthCode; | ||
use Doctrine\ORM\Mapping as ORM; | ||
|
||
/** | ||
* @ORM\Entity | ||
*/ | ||
class AuthCode extends BaseAuthCode | ||
{ | ||
/** | ||
* @ORM\Id | ||
* @ORM\Column(type="integer") | ||
* @ORM\GeneratedValue(strategy="AUTO") | ||
*/ | ||
protected $id; | ||
|
||
/** | ||
* @ORM\ManyToOne(targetEntity="Client") | ||
* @ORM\JoinColumn(nullable=false) | ||
*/ | ||
protected $client; | ||
|
||
/** | ||
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User") | ||
*/ | ||
protected $user; | ||
} | ||
|
||
``` | ||
|
||
`AppBundle/Entity/Client.php` | ||
|
||
```php | ||
<?php | ||
|
||
namespace AppBundle\Entity; | ||
|
||
use FOS\OAuthServerBundle\Entity\Client as BaseClient; | ||
use Doctrine\ORM\Mapping as ORM; | ||
|
||
/** | ||
* @ORM\Entity | ||
*/ | ||
class Client extends BaseClient | ||
{ | ||
/** | ||
* @ORM\Id | ||
* @ORM\Column(type="integer") | ||
* @ORM\GeneratedValue(strategy="AUTO") | ||
*/ | ||
protected $id; | ||
|
||
public function __construct() | ||
{ | ||
parent::__construct(); | ||
// your own logic | ||
} | ||
} | ||
|
||
``` | ||
|
||
`AppBundle/Entity/RefreshToken.php` | ||
|
||
```php | ||
<?php | ||
|
||
namespace AppBundle\Entity; | ||
|
||
use FOS\OAuthServerBundle\Entity\RefreshToken as BaseRefreshToken; | ||
use Doctrine\ORM\Mapping as ORM; | ||
|
||
/** | ||
* @ORM\Entity | ||
*/ | ||
class RefreshToken extends BaseRefreshToken | ||
{ | ||
/** | ||
* @ORM\Id | ||
* @ORM\Column(type="integer") | ||
* @ORM\GeneratedValue(strategy="AUTO") | ||
*/ | ||
protected $id; | ||
|
||
/** | ||
* @ORM\ManyToOne(targetEntity="Client") | ||
* @ORM\JoinColumn(nullable=false) | ||
*/ | ||
protected $client; | ||
|
||
/** | ||
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User") | ||
*/ | ||
protected $user; | ||
} | ||
|
||
``` | ||
|
||
`AppBundle/Entity/User.php` | ||
|
||
Add the file from the [FOSUserBundle Integration](fosuser-bundle.md#creating-a-user-entity-with-serialization-groups). | ||
|
||
## Security Configuration | ||
|
||
```yaml | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
# To get started with security, check out the documentation: | ||
# http://symfony.com/doc/current/book/security.html | ||
security: | ||
|
||
encoders: | ||
FOS\UserBundle\Model\UserInterface: bcrypt | ||
|
||
providers: | ||
fos_user_bundle: | ||
id: fos_user.user_provider.username | ||
|
||
firewalls: | ||
# disables authentication for assets and the profiler, adapt it according to your needs | ||
dev: | ||
pattern: ^/(_(profiler|wdt)|css|images|js)/ | ||
security: false | ||
|
||
oauth_token: | ||
pattern: ^/oauth/v2/token | ||
security: false | ||
|
||
oauth_authorize: | ||
pattern: ^/oauth/v2/auth | ||
# Add your favorite authentication process here | ||
|
||
api_docs: | ||
pattern: ^/(|docs.json|docs.jsonld|index.json)$ | ||
form_login: false | ||
provider: fos_user_bundle | ||
http_basic: | ||
realm: "Please enter your login data." | ||
|
||
api: | ||
pattern: ^/.+ | ||
fos_oauth: true | ||
stateless: true | ||
anonymous: true | ||
|
||
access_control: | ||
- { path: ^/.+, roles: [ IS_AUTHENTICATED_FULLY ] } | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra line to remove |
||
``` | ||
|
||
## Routing Configuration | ||
|
||
```yaml | ||
api: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
resource: '.' | ||
type: 'api_platform' | ||
|
||
fos_oauth_server_token: | ||
resource: "@FOSOAuthServerBundle/Resources/config/routing/token.xml" | ||
|
||
fos_oauth_server_authorize: | ||
resource: "@FOSOAuthServerBundle/Resources/config/routing/authorize.xml" | ||
``` | ||
|
||
## Create clients | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
Add this class to `AppBundle/Command/CreateOAuthClientCommand.php` to generate oauth clients via console: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OAuth |
||
|
||
```php | ||
<?php | ||
|
||
namespace AppBundle\Command; | ||
|
||
use AppBundle\Entity\Client; | ||
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; | ||
use Symfony\Component\Console\Input\InputArgument; | ||
use Symfony\Component\Console\Input\InputInterface; | ||
use Symfony\Component\Console\Output\OutputInterface; | ||
use Symfony\Component\HttpFoundation\Request; | ||
|
||
class CreateOAuthClientCommand extends ContainerAwareCommand | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you mark this class |
||
{ | ||
protected function configure() | ||
{ | ||
$this | ||
->setName('oauth:client:create') | ||
->setDescription('Create OAuth Client') | ||
->addArgument( | ||
'grantType', | ||
InputArgument::REQUIRED, | ||
'Grant Type?' | ||
) | ||
->addArgument( | ||
'redirectUri', | ||
InputArgument::OPTIONAL, | ||
'Redirect URI?' | ||
); | ||
} | ||
|
||
protected function execute(InputInterface $input, OutputInterface $output) | ||
{ | ||
$container = $this->getContainer(); | ||
$redirectUri = $input->getArgument('redirectUri'); | ||
$grantType = $input->getArgument('grantType'); | ||
|
||
$clientManager = $container->get('fos_oauth_server.client_manager.default'); | ||
/** @var Client $client */ | ||
$client = $clientManager->createClient(); | ||
$client->setRedirectUris($redirectUri ? [$redirectUri] : []); | ||
$client->setAllowedGrantTypes([$grantType]); | ||
$clientManager->updateClient($client); | ||
|
||
$output->writeln(sprintf("<info>The client <comment>%s</comment> was created with <comment>%s</comment> as public id and <comment>%s</comment> as secret</info>", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you switch to single quotes? |
||
$client->getId(), | ||
$client->getPublicId(), | ||
$client->getSecret() | ||
)); | ||
} | ||
} | ||
``` | ||
|
||
Now you can generate two clients. One for our swagger api documentation and one for our application that wants to get data from our api. | ||
|
||
```bash | ||
# Swagger api documentation client | ||
php bin/console oauth:client:create password | ||
|
||
# Application client | ||
php bin/console oauth:client:create client_credentials | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the comments are switched. The 2nd one should be the swagger one. |
||
``` | ||
|
||
## OAuth2 Configuration | ||
|
||
Add the following code to your `app/config/config.yml` and replace the `clientId` and `clientSecret` with the data from the generated application client with the `client_credentials` grant type. | ||
|
||
```yaml | ||
# ... | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
fos_oauth_server: | ||
db_driver: orm # Drivers available: orm, mongodb, or propel | ||
client_class: AppBundle\Entity\Client | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you remove indentation and put class names into single quotes (it can cause issues without single quotes when the class name contains special chars like |
||
access_token_class: AppBundle\Entity\AccessToken | ||
refresh_token_class: AppBundle\Entity\RefreshToken | ||
auth_code_class: AppBundle\Entity\AuthCode | ||
service: | ||
user_provider: fos_user.user_provider.username | ||
options: | ||
access_token_lifetime: 10800 | ||
supported_scopes: user | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a bit weird, as it will add ROLE_USER to every authentication, even the client_credentials one, when no user is present. This may lead to problems... in my case, the user is not allowed to list all users: access_control:
- { path: ^/users, roles: [ ROLE_ADMIN ] } but it will appear in the docs, and the request fails. I think there should be a hint about this. Also, from now on user should be null checked even if the ROLE_USER is available. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this ever got into official docs? Installing fresh api-platform, doesn't contain this .md file. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The full docs are available here: https://api-platform.com/docs I really want to merge this one, but it need to be rebased and finished first... |
||
|
||
api_platform: | ||
# ... | ||
oauth: | ||
enabled: true | ||
clientId: 'enter-swagger-api-documentation-client-id' | ||
clientSecret: 'enter-swagger-api-documentation-client-secret' | ||
``` | ||
|
||
That's all, now your OAuth2 authentication should work. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra line to remove. |
||
|
||
Previous chapter: [FOSUserBundle Integration](fosuser-bundle.md) | ||
|
||
Next chapter: [Adding a JWT authentication using `LexikJWTAuthenticationBundle`](jwt.md) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We use Title Case: