Symfony API: Authorization

View on Github

Symfony API: Authorization

Community maintained

This tutorial demonstrates how to add authentication and authorization to a Symfony API. We recommend you to Log in to follow this quickstart with examples configured for your account.

Or

I want to explore a sample app

2 minutes

Get a sample configured with your account settings or check it on Github.

View on Github
System requirements: PHP 5.5 | Symfony 3.3

New to Auth0? Learn how Auth0 works and read about implementing API authentication and authorization using the OAuth 2.0 framework.

Configure Auth0 APIs

Create an API

In the APIs section of the Auth0 dashboard, click Create API. Provide a name and an identifier for your API, for example https://quickstarts/api. You will use the identifier as an audience later, when you are configuring the Access Token verification. For Signing Algorithm, select RS256.

Create API

By default, your API uses RS256 as the algorithm for signing tokens. Since RS256 uses a private/public keypair, it verifies the tokens against the public key for your Auth0 account. The public key is in the JSON Web Key Set (JWKS) format, and can be accessed here.

Define scopes

Scopes let you define which resources can be accessed by the user with a given Access Token. For example, you might choose to grant read access to the messages resource if users have the manager access level, and a write access to that resource if they have the administrator access level.

You can add the required scopes in the Scopes tab of the Auth0 Dashboard's APIs section.

Configure Scopes

This example uses the read:messages scope.

This example demonstrates:

  • How to check for a JSON Web Token (JWT) in the Authorization header of an incoming HTTP request.

  • How to check if the token is valid, using the JSON Web Key Set (JWKS) for your Auth0 account. To learn more about validating Access Tokens, read the Verify Access Tokens tutorial.

Validate Access Tokens

Install dependencies

Protecting a Symfony API with Auth0 requires the jwt-auth-bundle package. Install it using composer.

Composer is a tool for dependency management in PHP. It allows you to declare the dependent libraries your project needs and it will install them in your project for you. See Composer's getting started doc for information on how to use it.

composer require auth0/jwt-auth-bundle:"^3.0"

v3.x.x of the jwt-auth-bundle provides compatibility with Symfony 3. For Symfony 2.x support, use the v1 branch.

Add the bundle to AppKernel.php

// app/AppKernel.php

class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = array(

            // ...
            new \Auth0\JWTAuthBundle\JWTAuthBundle(),

        );

        // ...
        return $bundles;
    }

Add configuration values

Add your Auth0 domain and API audience to the config.yml file located in app/config.

jwt_auth:
    domain: YOUR_AUTH0_DOMAIN
    authorized_issuer: https://YOUR_AUTH0_DOMAIN/
    api_identifier: YOUR_API_IDENTIFIER

Set up the User and UserProvider

Create your User and UserProvider.

The UserProvider must implement the JWTUserProviderInterface (see /source/AppBundle/Security/A0UserProvider). This class should implement two methods:

  • loadUserByJWT: receives the decoded JWT Access Token and returns a User.

  • getAnonymousUser: returns an anonymous user that represents an unauthenticated one (usually represented by the role IS_AUTHENTICATED_ANONYMOUSLY).

Both of the above methods can throw an AuthenticationException. If this exception is thrown by loadUserByJWT, the it will treat the user as being anonymous. If getAnonymousUser throw this exception, a 401 Unauthorized will be returned.

Provide configuration for the UserProvider in the services.yml file located in app/config.

services:
    a0_user_provider:
        class: AppBundle\Security\A0UserProvider
        arguments: ["@jwt_auth.auth0_service"]

Set up the SecurityProvider

Modify the security.yml file located in app/config such that it contains the following:

  • The UserProvider
  • The secured area that you want to authenticate using an Access Token
  • The access_control section with the roles needed for each route
security:
    providers:
        a0:
            id:
                a0_user_provider

    firewalls:
        secured_area:
            pattern: ^/api
            stateless: true
            simple_preauth:
                authenticator: jwt_auth.jwt_authenticator

    access_control:
        - { path: ^/api/private-scoped, roles: ROLE_OAUTH_READER }
        - { path: ^/api/private, roles: ROLE_OAUTH_AUTHENTICATED }
        - { path: ^/api/public, roles: IS_AUTHENTICATED_ANONYMOUSLY }

Protect API Endpoints

The routes shown below are available for the following requests:

  • GET /api/public: available for non-authenticated requests
  • GET /api/private: available for authenticated requests containing an Access Token with no additional scopes
  • GET /api/private-scoped: available for authenticated requests containing an Access Token with the read:messages scope granted
// src/AppBundle/Controller/SecuredController.php

// ...
class SecuredController extends Controller
{
    /**
     * @Route("/api/public", name="public")
     */
    // This route doesn't need authentication
    public function publicAction()
    {
        return new JsonResponse(array(
          'message' => "Hello from a public endpoint! You don't need to be authenticated to see this."
        ));
    }
    /**
     * @Route("/api/private", name="private")
     */
    public function privateAction()
    {
        return new JsonResponse(array(
          'message' => "Hello from a private endpoint! You need to be authenticated to see this."
        ));
    }
    /**
     * @Route("/api/private-scoped", name="privatescoped")
     */
    public function privateScopedAction()
    {
        return new JsonResponse(array(
          'message' => "Hello from a private endpoint! You need to be authenticated and have a scope of read:messages to see this."
        ));
    }
}

With this configuration in place, only calls that include Access Tokens which have a scope of read:messages will be allowed to access this endpoint.

Use Auth0 for FREE