title: How to protect the resources of a user in a REST API with FOSRestBundle and FOSOauthServerBundle?
body: <p>I'm developing a RESTful web service in Symfony2 with FOSRest and FOSOauthServer bundles (... and many others). My problem is that with an access token of other user, the api gives response instead of a 403 status code. For example:</p>
  
  <p>I have two users stored on database</p>
  
  <p>userA with tokenA
  userB with tokenB</p>
  
  <p>Example Request
  <a href="http://example.com/api/v1/userA/products?access_token=tokenB" rel="nofollow">http://example.com/api/v1/userA/products?access_token=tokenB</a></p>
  
  <p>Current Response</p>
  
  <pre><code>{
     products: {
      0: { ... } 
      1: { ... }
    }
  }
  </code></pre>
  
  <p>But I'm requesting products of user A with an access token of user B. How could I check if access token provided is of the products' owner??</p>
  
  <p>My security.yml file:</p>
  
  <pre><code>security:
      encoders:
          FOS\UserBundle\Model\UserInterface: sha512
  
      role_hierarchy:
          MY_ROLE:
              # ...
          ROLE_ADMIN:       ROLE_USER
          ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_SONATA_ADMIN, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
          SONATA:
              - ROLE_SONATA_PAGE_ADMIN_PAGE_EDIT
      providers:
          fos_userbundle:
              id: fos_user.user_provider.username_email
  
      firewalls:            
          admin:
              pattern:            /admin(.*)
              context:            user
              form_login:
                  provider:       fos_userbundle
                  csrf_provider:  form.csrf_provider
                  login_path:     /admin/login
                  use_forward:    false
                  check_path:     /admin/login_check
                  failure_path:   null
              logout: 
                  path:           /admin/logout
              anonymous:          true                
  
          # FOSOAuthBundle and FOSRestBundle    
          oauth_token:
              pattern:    ^/oauth/v2/token
              security:   false
  
  #        oauth_authorize: commented because there are not oauth login form on this app
  #            pattern:    ^/oauth/v2/auth
              # Add your favorite authentication process here
  
          api:
              pattern:    ^/api
              fos_oauth:  true
              stateless:  true
              anonymous:  false
  
          # This firewall is used to handle the public login area
          # This part is handled by the FOS User Bundle
          main:
              # ...
  
      access_control:
          # ...
  
          # API (FOSRestBundle and FOSOAuthBundle)
          - { path: ^/api, roles: [IS_AUTHENTICATED_FULLY] }
  </code></pre>
  
  <p>My routing.yml on ApiBundle</p>
  
  <pre><code># API Endpoints
  app_api_user_get_products:
      pattern: /{username}/products
      defaults: { _controller: ApiBundle:User:getProducts, _format: json }
      methods: GET
  </code></pre>
  
  <p>My UserController.php</p>
  
  <pre><code>&lt;?php
  
  namespace App\ApiBundle\Controller;
  
  Use App\MainBundle\Entity\Product;
  use Symfony\Component\HttpFoundation\Request;
  use Symfony\Component\HttpFoundation\Response;
  // ... more use statments
  
      class UserController extends ApiController {
  
      /**
       * List user's products.
       *
       * @ApiDoc(
       *  resource = true,
       *  description="This method must have the access_token parameter. The parameters limit and offset are optional.",
       *  filters={
       *      {"name"="access_token", "dataType"="string", "required"="true"},
       *      {"name"="offset", "dataType"="integer", "default"="0", "required"="false"},
       *      {"name"="limit", "dataType"="integer", "default"="250", "required"="false"}
       *  },
       * )
       *
       * @Annotations\QueryParam(name="offset", requirements="\d+", nullable=true, description="Offset from which to start listing products.")
       * @Annotations\QueryParam(name="limit", requirements="\d+", default="500", description="How many products to return.")
       *
       * @Annotations\View()
       *
       * @param User               $user      the request object
       * @param ParamFetcherInterface $paramFetcher param fetcher service
       *
       * @return array
       */
      public function getProductsAction(User $user, ParamFetcherInterface $paramFetcher, Request $request) { 
  
  
  //        $offset = $paramFetcher-&gt;get('offset');
  //        $offset = null == $offset ? 0 : $offset;
  //        $limit = $paramFetcher-&gt;get('limit');
  
          try {
              // estructure and exclude fields strategy http://jmsyst.com/libs/serializer/master/cookbook/exclusion_strategies
              $data = array('products' =&gt; array());
              foreach ($user-&gt;getCatalog() as $p) {
                  if ($p-&gt;getAvailable() == true) {
                      $product = $p-&gt;getProduct();
                      $data['products'][] = array(
                          'id' =&gt; $product-&gt;getId(),
                          'reference' =&gt; $product-&gt;getReference(),
                          'brand' =&gt; $product-&gt;getBrand(),
                          'description' =&gt; $product-&gt;getDescription(),
                          // ...
                      );
                  }
              }
          } catch (\Exception $e) {
              throw new HttpException(Codes::HTTP_INTERNAL_SERVER_ERROR, $e-&gt;getTraceAsString());
          }
  
          // New view
          $view = new View($data);
          $view-&gt;setFormat('json');
  
          return $this-&gt;handleView($view);
      }
  }
  </code></pre>
  
  <p>Thank you very much for the help!</p>