Laravel Passport usage with Swaggervel v2.3
Published: 2020-01-27 22:09:52

---
title: Laravel Passport usage with Swaggervel v2.3
published: true
date: 2018-07-10 20:30:00 UTC
tags: 
canonical_url: https://braytonium.com/2018/07/10/laravel-passport-usage-with-swaggervel-v2-3/
---

### Overview

I've been using [this Swaggervel package](https://github.com/appointer/swaggervel) with almost all my recent Laravel projects. A few instances were lightly customized to work against different authentication schemes and I only briefly touched on using Laravel Passport.

I wanted to highlight a few areas while also offering up [an example project](https://github.com/w0rd-driven/laravel-passport-swaggervel-example) as a lightly opinionated jumping off point. Just the highlights cover quite a bit of information but the example should have ample information in commit messages and in the finished product.

### Setting up Laravel and Laravel Passport

First we run `laravel new <project_name>`, `git init` and commit immediately to mark our base Laravel installation. I've always preferred this immediate commit over making customizations first as it's far easier to track your customizations versus the base install. Next, we run through [the Laravel Passport docs](https://laravel.com/docs/5.6/passport) with the following caveats:

- `php artisan vendor:publish --tag=passport-migrations` doesn't copy the migrations as expected. We manually do this.
- `php artisan migrate --step` creates a migration batch for each migration file individually. This lets us rollback to individual steps and is primarily personal preference.
- `app/Providers/AuthServiceProvider` contains the following:

```
Passport::routes(function (RouteRegistrar $routeRegistrar) {
    $routeRegistrar->all();
});
Passport::tokensCan([
]);
Passport::enableImplicitGrant();
Passport::tokensExpireIn(Carbon::now()->addDays(15));
Passport::refreshTokensExpireIn(Carbon::now()->addDays(30));
```

- Run `artisan make:auth` to utilize the app layout and create a `home` view that is protected by the Login prompt.
  - The Passport Vue components could be displayed on the welcome page but we're attempting to set future users up for better practices.
- Create a proper `WelcomeController` with matching view that utilizes the same app layout
  - This is not necessary but this one step makes it possible to properly utilize `artisan route:cache` in the future as route closures aren't supported.

### Setting up Swaggervel

Now that the basics are complete, we bring in Swaggervel via `composer require appointer/swaggervel --dev`. We can ignore the line in the documentation that mentions adding `Appointer\Swaggervel\SwaggervelServiceProvider::class` as that's only for Laravel versions earlier than 5.5 without package discovery. It's necessary to run `artisan vendor:publish` to publish the content as we're using this package as a dev dependency and the assets won't show up otherwise. Now that Swaggervel is in place we can bring it all together.

To start, we create the file `app/Http/Controllers/Api/v1/Controller.php` as our generic API base controller. This controller houses our root-level `@SWG\Info` definition in a convenient location. This also sets us up for future work where API controllers are versioned, though this is personal preference. The secret sauce is the `@SWG\SecurityScheme` annotation:

```
/**
 * @SWG\SecurityScheme(
 * securityDefinition="passport-swaggervel_auth",
 * description="OAuth2 grant provided by Laravel Passport",
 * type="oauth2",
 * authorizationUrl="/oauth/authorize",
 * tokenUrl="/oauth/token",
 * flow="accessCode",
 * scopes={
 * *
 * }
 * ),
 */
```

The `securityDefinition` property is arbitrary but needs to be included in every protected route definition. You can specify multiple security schemes to cover things like an generic api key or likely multiple OAuth flows, though I haven't tried working out the latter.[These are the supported flows](https://swagger.io/specification/#oauthFlowsObject) and it's important to note that Swaggervel is currently on the `OpenAPI 2.0` specification, though this may change in the future. The `scopes` specified includes everything (\*) but we could define any scopes explicitly. It should be noted that we also need to setup the route definitions in our resource Controller classes but due to the verbosity they are too much to include in this post. A small snippet that is unique to working with this setup is the following:

```
* security={
* {
* "passport-swaggervel_auth": {"*"}
* }
* },
```

This tells a specific endpoint to use the `securityDefinition` created earlier and it's important that these match. The example project has rudimentary `UserController`, `User` model, and `UserRequest` definitions that should be a decent starting point, though I can't vouch for them being very comprehensive.

### Configuring our OAuth Client

First we need to create an OAuth client specifically for Swaggervel connections. Go to the `/home` endpoint and under `OAuth Clients` click `Create New Client`. Under `Name` specify `Laravel Passport Swaggervel` or just `Swaggervel`. Under `Redirect URL` we're unable to specify `/vendor/swaggervel/oauth2-redirect.html` directly, so use a placeholder like `https://passport-swaggervel.test/vendor/swaggervel/oauth2-redirect.html` instead. Using your SQL toolbox of choice, navigate to the table `oauth_clients` and look for the row with the name specified in the previous step, in our case `Laravel Passport Swaggervel`. Manually update the redirect column to `/vendor/swaggervel/oauth2-redirect.html`.

Now that our OAuth client in Passport should be setup correctly, we focus our attention on the `config/swaggervel.php` settings. The `client-id` should be set to what Passport shows in the UI as the `Client ID` field. This is also the id of the row in the `oauth_clients` table. The `client-secret` should be set to the what Passport shows in the UI as the `Secret` field. We also set both `secure-protocol` and `init-o-auth` to true, the latter of which fills in the UI with our secrets otherwise we'd have to put them in manually.

### Correcting Swagger UI to Capture Tokens

For the OAuth2 redirect to function properly we need to modify the Swagger UI configuration in `resources/views/vendor/swaggervel/index.blade.php`. Under `const ui = SwaggerUIBundle({` right below the url parameter should be `oauth2RedirectUrl: '/vendor/swaggervel/oauth2-redirect.html',`. This reinforcement is necessary as the Swagger UI doesn't 'catch' the tokens properly without this. Other notable additions that make the UI slightly easier to work with:

```
tagsSorter: 'alpha',
operationsSorter: 'alpha',
docExpansion: 'list',
filter: true
```

### Testing Authentication via the Swagger UI

First we go to the `api/docs` endpoint to display the Swagger UI. Click the `Authorize` button with the unlocked padlock icon. Verify the `client_id` and `client_secret` sections are filled in. Click `Authorize` and the Laravel Passport screen labelled `Authorization Request` should display with the `Authorize` and `Cancel` buttons. Click `Authorize` again and you should be redirected back to Swagger with the `client_id` and `client_secret` now showing as ` ****** ` with a `Logout` button instead of `Authorize`. We should now be able to click on the `GET /users` route, click the `Try it out` button, click on the blue `Execute` button and be greeted with our expected response as a list of users.

### Conclusion

We've hopefully highlighted the basic touch points of the process with the example code going into much further detail. The project is lightly opinionated to facilitate practices that have served me well so far. It is by no means a complete reference but it should be a good jumping off point when it's somewhat harder to see the big picture without a comprehensive example.

In case you need the [link to the project again](https://github.com/w0rd-driven/laravel-passport-swaggervel-example).