Docs

Laravel API: Authorization

View on Github

Laravel API: Authorization

Gravatar for josh.cunningham@auth0.com
By Josh Cunningham

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

I want to explore a sample app

2 minutes

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

View on Github
System requirements: Composer 1.5 | PHP 7.0 | Laravel 5.5 | laravel-auth0 5.0.2

This quickstart covers building an API protected by an Auth0-issued access token. This type of API is typically consumed by:

If this API is only consumed by a web application on the same domain (in the case of AJAX actions or lazy loading content for an authenticated user) then the API protection should be handled by the application itself and the login flow secured by Auth0.

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 your Laravel API requires a middleware which will check for and verify a bearer token in the Authorization header of an incoming HTTP request. We'll do that using tools provided by the laravel-auth0 package.

Install laravel-auth0 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.

Configure the plugin

The laravel-auth0 plugin comes with a configuration file that can be generated using Artisan. First, generate the configuration file from the command line:

Select the Auth0\Login\LoginServiceProvider option. After the file is generated, it will be located at config/laravel-auth0.php. Edit this file to add the configuration values needed to verify incoming tokens:

In more detail:

  • authorized_issuers is an array of allowed token issuers. In this case it would simply be an array with just your tenant URL.
  • api_identifier is the Identifier field of the API created above.
  • supported_algs is the Signing Algorithm field of the API created above. This value should be an array but only have a single value, RS256.

Configure Apache

By default, Apache does not parse Authorization headers from incoming HTTP requests. You may need to add the following to the .htaccess file for your application:

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

For the two private API routes, we'll need a middleware to check for a bearer token in an Authorization header for the request and then verify that the token is valid. We'll create that middleware using the make:middleware Artisan command:

Now, let's implement the handle() method that Laravel will call automatically for the route:

This middleware:

  • Checks that there is a Bearer token and stops the request if one was not found.
  • Pulls in the configuration values needed to verify the token.
  • Attempts to decode the token, catching any exceptions thrown if it is expired, malformed, or otherwise invalid.

Next, we register this middleware we in the HTTP Kernel with the name jwt:

We are now able to protect individual API endpoints by applying the jwt middleware:

The /api/private route is now only accessible if a valid Access Token is included in the Authorization header of the incoming request. We can test this by manually generating an Access Token for the API and using a tool like Postman to test the routes.

In the Auth0 Dashboard:

  1. Go to the Machine to Machine Applications tab for the API created above.
  2. Authorize the API Explorer Application but leave all scopes unchecked.
  3. Click the Test tab, then COPY TOKEN.

Now, let's turn on the Laravel test server:

Send a GET request to the public route - http://localhost:3000/api/public - and you should receive back:

Now send a GET request to the private route - http://localhost:3000/api/private - and you should get a 401 status and the following message:

Add an Authorization header set to Bearer API_TOKEN_HERE using the token generated above. Send the GET request to the prviate route again and you should see:

Configure the Scopes

The middleware we created above checks for the existence and validity of an Access Token but does not check the scope of the token. In this section, we will modify the middleware created above to check for specific scopes.

Here are the changes to make to the CheckJWT middleware created above:

In summary:

  • We added a $scopeRequired parameter to the handle() method with a default value of null. This will allow us to still handle private routes that do not need to check scope.
  • At the end of handle(), we check if the route requires a scope and, if so, that the token includes it.
  • We added a tokenHasScope() method to look for a specific scope within a decoded token.

Now, we can create a new middleware group that will check for both a valid token and a specific scope:

This route is now only accessible if an Access Token used in the request has a scope of read:messages.

To test this route, first send a GET request with no token to the private, scoped route - http://localhost:3000/api/private-scoped - and you should get a 401 status and the following message:

Add an Authorization header set to Bearer API_TOKEN_HERE using the same token from the previous section. Send the GET request to the prviate, scoped route again and you should get a 403 status and the following message:

Back in the Auth0 Dashboard:

  1. Go to the Machine to Machine Applications tab for the API created above.
  2. Expand the API Explorer Application, check the read:messages scope,and click Update
  3. Click the Test tab, then COPY TOKEN.

Change the Authorization header to use the new token and send the GET request again. You should get a 200 status and the following message:

Obtaining Access Tokens

The example above uses manually-generated tokens which are not long-lived. Once your API is live on the web and ready to accept requests, the applications making the requests will need to create their tokens using one of a few ways:

Regardless of the type, the application will need to request the audience of this API during the login flow to receive a correctly-formed access token.

Configure CORS (optional)

To configure CORS, you should add the laravel-cors dependency. You can check it out here.

After installation, add HandleCors middleware in the application's global middleware stack:

Add the following to the configuration file for CORS:

Use Auth0 for FREE