logo

API authentication σε Laravel και χρήση του εσωτερικά της εφαρμογής από Vue κομμάτια

02/04/2020

Εντάξει. Είναι λίγο μπερδεμένος ο τίτλος. Να εξηγήσω λίγο περισσότερο.

Ας πούμε ότι γράφουμε μια εφαρμογή σε Laravel, αλλά υπάρχουν κάποια κομμάτια του frontend, μέσα στα blade views μας, που χρησιμοποιούμε και λίγο Vue.

Για παράδειγμα, σε ένα view που κάνουμε post ένα άρθρο. Σε ένα σημείο μπορεί να θέλουμε να περνάμε tags, με έναν πιο διαδραστικό και άμεσο τρόπο, χρησιμοποιώντας Vue. Δηλαδή προσθέτουμε tag κι αυτό εισάγεται άμεσα στην βάση δεδομένων με ένα API call.

Το API call αυτό θα κάνει φυσικά ένα POST. Ας πούμε ότι ο κώδικας μας κάνει περίπου κάτι τέτοιο:

insertTag(e) 
{
   let myData = {
       name: this.tag
   }

   axios.post('/api/tag', myData)
       .then(response => {
           this.tags.push({
                id: response.data.id, 
                name: response.data.name
             })
           this.tag = ''
        })
        .catch(e => console.log(e))
}

Όπως βλέπουμε, πρέπει να γίνει κλήση στο /api/tag. Όμως καταλαβαίνουμε ότι POST σε αυτό το route δεν πρέπει να μπορεί να κάνει οποιοσδήποτε, αλλά κάποιος authenticated χρήστης.

To Laravel έχει ήδη έναν μηχανισμό. Στο αρχείο config/auth.php, υπάρχει ένας API guard που υλοποιεί έναν token driver. O driver αυτός ελέγχει για API token στα εισερχόμενα requests και ελέγχει αν αυτό ανήκει στον συγκεκριμένο χρήστη.

Παρ’ όλα αυτά, εμείς πρέπει να κάνουμε και μερικά ακόμη πράγματα.

Καταρχήν πρέπει να προσθέσουμε το πεδίο api_token στο migration του table users. π.χ.

$table->string('api_token', 80)->after('password')
                        ->unique()
                        ->nullable()
                        ->default(null);

Πρέπει κάθε φορά που δημιουργούμε ή κάνουμε update έναν χρήστη να δημιουργείται και το api_token για τον συγκεκριμένο χρήστη. π.χ. στο αρχείο Http/Controllers/Auth/RegisterController.php που γίνεται register ο νέος χρήστης, μπορούμε να προσθέσουμε κάτι τέτοιο, στην μέθοδο create:

return User::create([
        'name' => $data['name'],
        'email' => $data['email'],
        'password' => Hash::make($data['password']),
        'api_token' => Str::random(80)
    ]);

Αντίστοιχα στο UserFactory.php, αν χρησιμοποιούμε, προσθέτουμε ένα αντίστοιχο πεδίο

'api_token' => Str::random(80)

Και φυσικά όπου αλλού στον κώδικα μας μπορεί να χρειαστεί να δημιουργηθεί ή να γίνει update ο χρήστης.

Ας πάμε τώρα στην τελική υλοποίηση. Προσθέτουμε στο routes/api.php, κάτω από το middleware auth:api, όποια API routes χρειάζονται authentication. π.χ.

Route::group(['middleware' => 'auth:api'], function() {
    Route::post('tag', 'AdminTagsController@store');
});

Το api_token θα πρέπει να το περνάμε στο blade view, όπου θα χρησιμοποιηθεί για να γίνει το API call. Πάμε π.χ. στον αντίστοιχο controller, στην μέθοδο που κάνει create την φόρμα για το post άρθρου. Προσθέτουμε κάτι τέτοιο:

public function create()
    {
        $user_id = Auth::id();
        $userApiToken = Auth::user()->api_token;

        return view('admin.posts.create', compact('user_id', 'userApiToken'));
    }

Χρησιμοποιούμε δηλαδή το Auth::user()->api_token για να πάρουμε το api_token του χρήστη. Αυτό το περνάμε στο view που θα το χρειαστούμε.

Κάπου μέσα στο blade view θα πρέπει να μπει ο παρακάτω κώδικας, για να περνάει στην javascript το api_token.

<script>
 let LaravelAuth = @json([
    'apiToken' => $userApiToken ?? null,
 ]);
</script>

Τέλος, στο αρχείο resources/assets/js/bootstrap.js, θα πρέπει να περνάμε το token στα headers του Axios. Θα πρέπει να έχει δηλαδή κάτι τέτοιο:

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

if(typeof LaravelAuth !== 'undefined') {
    window.axios.defaults.headers.common['Authorization'] = 'Bearer ' + LaravelAuth.apiToken;
}

Αυτό ήταν. Από εδώ και πέρα στα συγκεκριμένα routes που βάζουμε κάτω από το middleware auth.api, θα γίνεται έλεγχος για authentication.

Περισσότερα μπορείτε να βρείτε και στο documentation του Laravel. Παίζει όλη η μέθοδος να έχει αλλάξει με το Sanctum. Δεν το έχω ψάξει ακόμη όμως με αυτό και προς το παρόν στις εφαρμογές μου χρησιμοποιώ την παραπάνω μέθοδο.

Write your comment

rocean (at) error.gr
rocean
error.gr
feed