Skip to content
Closed
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/fosuser-bundle.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,4 @@ class User extends BaseUser

Previous chapter: [Accept application/x-www-form-urlencoded Form Data](form-data.md)

Next chapter: [Adding a JWT authentication using `LexikJWTAuthenticationBundle`](jwt.md)
Next chapter: [Adding a OAuth2 authentication using `FOSOAuthServerBundle`](oauth2.md)
4 changes: 2 additions & 2 deletions core/jwt.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ security:
providers:
fos_userbundle:
id: fos_user.user_provider.username

firewalls:
login:
pattern: ^/login
Expand Down Expand Up @@ -60,6 +60,6 @@ security:
- { path: ^/, roles: [ ROLE_READER ] }
```

Previous chapter: [FOSUserBundle Integration](fosuser-bundle.md)
Previous chapter: [Adding a OAuth2 authentication using `FOSOAuthServerBundle`](oauth2.md)

Next chapter: [NelmioApiDocBundle integration](nelmio-api-doc.md)
340 changes: 340 additions & 0 deletions core/oauth2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,340 @@
# Adding a OAuth2 authentication using `FOSOAuthServerBundle`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use Title Case:

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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you remove the [1] please as the reference is not in this document.


[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(
Copy link
Member

Choose a reason for hiding this comment

The 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating Entities to Store OAuth2 Data


Add all the following classes to your entities and run `php bin/console doctrine:schema:update --force`:

`AppBundle/Entity/AccessToken.php`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We put the filename as a comment just after <?php directly in the code sample (same for all other files).


```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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

# app/config/security.yml

# 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 ] }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra line to remove

```

## Routing Configuration

```yaml
api:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

# app/config/routing.yml

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating Clients


Add this class to `AppBundle/Command/CreateOAuthClientCommand.php` to generate oauth clients via console:
Copy link
Member

Choose a reason for hiding this comment

The 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you mark this class final please?

{
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>",
Copy link
Member

Choose a reason for hiding this comment

The 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
Copy link

Choose a reason for hiding this comment

The 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
# ...
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

# app/config/config.yml

fos_oauth_server:
db_driver: orm # Drivers available: orm, mongodb, or propel
client_class: AppBundle\Entity\Client
Copy link
Member

Choose a reason for hiding this comment

The 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 \t)

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
Copy link

@Padam87 Padam87 May 5, 2017

Choose a reason for hiding this comment

The 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.

Choose a reason for hiding this comment

The 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.
Where is this file located, where we can read the full doc?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The full docs are available here: https://api-platform.com/docs
And also in this GitHub repository.

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.

Copy link
Member

Choose a reason for hiding this comment

The 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)
15 changes: 11 additions & 4 deletions index.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
1. [Max Joins](core/performance.md#max-joins)
2. [Force Eager](core/performance.md#force-eager)
3. [Override at Resource and Operation Level](core/performance.md#override-at-resource-and-operation-level)
4. [Disable Eager Loading](core/performance.md#disable-eager-loading)
4. [Disable Eager Loading](core/performance.md#disable-eager-loading)
18. [Operation Path Naming](core/operation-path-naming.md)
1. [Configuration](core/operation-path-naming.md#configuration)
2. [Create a Custom Operation Path Naming](core/operation-path-naming.md#create-a-custom-operation-path-resolver)
Expand All @@ -80,9 +80,16 @@
19. [Accept `application/x-www-form-urlencoded` Form Data] (core/form-data.md)
20. [FOSUserBundle Integration](core/fosuser-bundle.md)
1. [Creating a `User` Entity with Serialization Groups](core/fosuser-bundle.md#creating-a-user-entity-with-serialization-groups)
21. [Adding a JWT authentication using LexikJWTAuthenticationBundle](core/jwt.md)
22. [NelmioApiDocBundle integration](core/nelmio-api-doc.md)
23. [AngularJS Integration](core/angularjs-integration.md)
21. [Adding a OAuth2 authentication using `FOSOAuthServerBundle`](oauth2.md)
1. [Install FOSOauthServerBundle](oauth2.md#install-fosoauthserverbundle)
2. [Create oauth2 entites](oauth2.md#create-oauth2-entites)
3. [Security Configuration](oauth2.md#security-configuration)
4. [Routing Configuration](oauth2.md#routing-configuration)
5. [Create clients](oauth2.md#create-clients)
6. [OAuth2 Configuration](oauth2.md#oauth2-configuration)
22. [Adding a JWT authentication using LexikJWTAuthenticationBundle](core/jwt.md)
23. [NelmioApiDocBundle integration](core/nelmio-api-doc.md)
24. [AngularJS Integration](core/angularjs-integration.md)
1. [Restangular](core/angularjs-integration.md#restangular)
2. [ng-admin](core/angularjs-integration.md#ng-admin)

Expand Down