How to Secure Laravel API (sanctum)

Viewed 273

I have a laravel application with a login system, only for interns and I have a Website which gets and posts data from/to the laravel application with a api

So i want, that only my website can get/post data from/to the api -> laravel app

For now, i've created a login user for the api with email and password. I know thats not the right way to do it.

And with this login credentials the website gets a bearer token from the api (expiration 10 min)

With this bearer token (header of ajax call) the website calls every api request (get/post)

Code:

Ajax call to get Bearer Token:

 axios.post(data_source_url + "/auth/token", {'email' : 'api@email.de', 'password' : 'pw1'}).then((res) => {
        document.cookie = 'bearer=' + res.data + ';expires=' ...
    })

Laravel Api Routes:

Route::post('/auth/token', ['uses'=>'ApiController@getToken'])->name('api.getToken');
Route::get('/get', ['middleware'=>'auth:sanctum', 'uses'=>'Api\ApiController@read']);
Route::post('/send', ['middleware'=>'auth:sanctum', 'uses'=>'Api\ApiController@send']);

so I would like to leave it that way with authorise with a bearer token, but how to send and receive a bearer token from the api the right/secure way, because the way i do it right now with the login is totally insecure

1 Answers

You should not leave open your route to get the token. I've written an article in this matter Laravel 8 REST API This approach lets you get a token by first logging in with a valid user to the app. For your use case, you just remove the register route and controller, and you will be able to secure it just for your use.

Route

Route::post('/login', [ApiController::class, 'login']);

Controller

public function login(Request $request) {
     if (!Auth::attempt($request->only('email', 'password'))) {
     return response()->json(['message' => 'Incorrect e-mail or password'], 401);
    }

    $user = User::where('email', $request['email'])->firstOrFail();

    $token = $user->createToken('auth_token')->plainTextToken;

    return response()->json([
        'access_token' => $token,
        'token_type' => 'Bearer',
    ]);
}

I just realized you are logging in to retrieve the bearer. Relax, headers are encrypted using HTTPS, so it is secure as far as I know.

In order to remove the plaintext user and password in the js call, you need to install dotenv by issuing npm install dotenv --save

Now add to your .env file

MY_API_USER=api@email.de
MY_API_PASSWORD=pw1

Then you need to add to your file

require('dotenv').config();

So you can use the sensitive data this way

axios.post(data_source_url + "/auth/token", {'email' : process.env.MY_API_USER, 'password' : process.env.MY_API_USER}).then((res) => {
    document.cookie = 'bearer=' + res.data + ';expires=' ...
})

You won't share your .env file, and be sure to add it to your .gitignore or similar, if it is not there.

Related