Laravel JWT Auth with Vue.js 2

Vue Resource

In order to post the Registration form data, the Vue.js resource plugin needs to be installed.

npm i vue-resource --save-dev

Update resources/js/app.js to import the vue-resource plugin after the vue-router.

Add the Vue.use statement for the vue-resource.

Add the Vue.http.headers and Vue.http.options.root url.

Laravel VerifyCsrfToken middleware will check for the X-CSRF-TOKEN request header. To make this token available to the client side script, it is being stored in the csrf-token meta tag near the top of the web page. The Authorization header is needed for JWT auth which will be added with the sign-in form later.

app.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import VueResource from 'vue-resource';

...

Vue.use(VueRouter);
Vue.use(VueResource);

Vue.http.headers.common['X-CSRF-TOKEN'] = document.getElementsByName('csrf-token')[0].getAttribute('content');
Vue.http.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('id_token');
Vue.http.options.root = 'http://laravel.dev:8080';

...

Create a resources/js/auth.js JavaScript file.

touch assets/js/auth.js

Add code to auth.js to set the default user and register form handler.

auth.js
import Vue from './app.js';
import {router} from './app.js';

export default {
    user: {
        authenticated: false,
        profile: null
    },
    register(context, name, email, password) {
        Vue.http.post(
            'api/register',
            {
                name: name,
                email: email,
                password: password
            }
        ).then(response => {
            context.success = true
        }, response => {
            context.response = response.data
            context.error = true
        })
    }
}

Add a script to the bottom of the Register.vue file for the default data and register form handler.

Register.vue
...

</template>

<script>
import auth from '../js/auth.js';

export default {
    data() {
        return {
            name: null,
            email: null,
            password: null,
            success: false,
            error: false,
            response: null
        }
    },
    methods: {
        register(event) {
            event.preventDefault()
            auth.register(this, this.name, this.email, this.password)
        }
    }
}
</script>

API

For form validation, generate a FormRequest class using artisan.

php artisan make:request RegisterFormRequest

Edit app/Http/Requests/RegisterFormRequest.php. First, return true instead of false in the authorize function since using JWT for that. Then add the validation rules in the array that is returned in the rules function for the new User.

RegisterFormRequest.php
public function authorize()
{
    return true;
}

...

public function rules()
{
    return [
        'name' => 'required',
        'email' => 'required|email|unique:users',
        'password' => 'required',
    ];
}

Edit the pre-existing app/Http/Controllers/Auth/AuthController.php. Replace everything below the namespace declaration with this code.

AuthController.php
...

use App\Models\User;
use App\Http\Controllers\Controller;
use App\Http\Requests\RegisterFormRequest;
use Illuminate\Http\Request;

class AuthController extends Controller
{
    public function register(RegisterFormRequest $request)
    {
        User::create([
            'name' => $request->json('name'),
            'email' => $request->json('email'),
            'password' => bcrypt($request->json('password')),
        ]);
    }
}

Test the form and API by registering a new user. Check the users table in the database for a new row for the user that was just added. Try registering another new user with the same e-mail address to test the validation.

JWT Auth

For Laravel JSON web token authentication, install jwt-auth using composer require.

composer require tymon/jwt-auth

Edit config\app.php adding the service JWTAuthServiceProvider to the providers array and under the aliases array, add the JWTAuth facade.

app.php
...

'providers' => [
    ...

    Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class,
]

...

'aliases' => [
    ...

    'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class,
]

Publish the configuration.

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"

Generate a key in the published configuration.

php artisan jwt:generate

Edit the published configration config\jwt.php file by updating 'user' => 'App\User' since the User model namespace has been changed from the default.

jwt.php
...

'user' => App\Models\User::class,

User Endpoint

Create the User controller.

php artisan make:controller UserController

Edit the app\Http\Controllers\UserController.php adding the index method to return the user data.

UserController.php
...

use Illuminate\Http\Request;

use App\Http\Requests;

class UserController extends Controller
{
    public function index(Request $request)
    {
        $data = [];
        $data['name'] = $request->user()->name;
        $data['email'] = $request->user()->email;
        return response()->json([
            'data' => $data,
        ]);
    }
}

Add the signin method to the AuthController class and update the use statements for the external classes.

AuthController.php
...

use App\Models\User;
use App\Http\Controllers\Controller;
use App\Http\Requests\RegisterFormRequest;
use Carbon\Carbon;
use JWTAuth;
use Illuminate\Http\Request;
use Tymon\JWTAuth\Exceptions\JWTException;

class AuthController extends Controller
{
    public function register(RegisterFormRequest $request)
    {
        User::create([
            'name' => $request->json('name'),
            'email' => $request->json('email'),
            'password' => bcrypt($request->json('password')),
        ]);
    }

    public function signin(Request $request)
    {
        try {
            $token = JWTAuth::attempt($request->only('email', 'password'), [
                'exp' => Carbon::now()->addWeek()->timestamp,
            ]);
        } catch (JWTException $e) {
            return response()->json([
                'error' => 'Could not authenticate',
            ], 500);
        }

        if (!$token) {
            return response()->json([
                'error' => 'Could not authenticate',
            ], 401);
        } else {
            $data = [];
            $meta = [];

            $data['name'] = $request->user()->name;
            $meta['token'] = $token;

            return response()->json([
                'data' => $data,
                'meta' => $meta
            ]);
        }
    }
}

Edit app\Http\Kernel.php adding jwt.auth to the application’s route middleware array.

kernel.php
...

protected $routeMiddleware = [
    ...

    'jwt.auth' => \Tymon\JWTAuth\Middleware\GetUserFromToken::class,
];

Edit app\Http\routes.php – at the bottom of the file, add the signin and jwt.auth route group to authorize access to the user endpoint.

routes.php
...

Route::group(['middleware' => ['api']], function () {
    Route::post('/api/register', [
        'uses' => 'Auth\AuthController@register',
    ]);

    Route::post('/api/signin', [
        'uses' => 'Auth\AuthController@signin',
    ]);

    Route::group(['middleware' => 'jwt.auth'], function () {
        Route::get('/user', [
            'uses' => 'UserController@index',
        ]);
    });

});

The last page covers the rest of the front end code including sign in, sign out and navigation updates.


Published by

Jim Frenette

Web Developer - views here are my own except those taken from people more clever than me.

Loading Disqus Comments ...
Loading Facebook Comments ...