در OAuth 2 ، نوع احراز هویت Password Grant به ما این امکان را میدهد تا در برنامهای که متعلق به خودمان است(first party app)، با استفاده از آدرس ایمیل/نام کاربری و رمز عبور، access token دریافت کنیم. این قابلیت باعث میشود بدون این که همه مراحل authorization code در oauth را طی کنیم به شیوهای امن access token را دریافت کنیم.
ایجاد کلاینت Password Grant روی سرور OAuth
قبل از این که برنامه ما بتواند توکنها را از طریق password grant صادر کند، نیاز به ایجاد یک کلاینت داریم که با password grant کار کند. برای این کار میتوانیم از دستور passport:client
با گزینه password
استفاده کنیم. اما اگر قبلا دستور passport:install را اجرا کرده باشیم، نیازی به اجرای این دستور نیست. ما قبلا این کار را انجام دادهایم و دیگر نیازی به این کار نمیباشد. اما جهت نشان دادن به شما، میخواهیم یک بار این کار را انجام دهیم. پس دستور را اجرا میکنیم:
php artisan passport:client --password
با اجرای این دستور تعدادی سؤال از ما پرسیده میشود که در شکل زیر نشان داده شده است. ما برای پاسخ به این سؤالات از جواب های پیشفرض استفاده کردیم. یعنی با زدن کلید Enter از آنها عبور کردیم.
اگر میخواهید خروجی آن را مشاهده کنید میتوانید به دیتابیس مراجعه کرده که در حقیقت در جدول oauth_clients، یک رکورد جدید با Client ID و Secret نشان داده شده است.
اکنون ما یک کلاینت password grant ایجاد کردهایم. بسیار خوب. بهتر است به سراغ اصل مطلب برویم. برای این که یک کلاینت روی سرور اصلی خود یعنی برنامه ToDo داشته باشیم، یک صفحه SPA با استفاده از vue ایجاد میکنیم. ابتدا به مسیر resources/js/components/ رفته و یک فایل جدید با نام Client.vue ایجاد میکنیم. در تگ template این فایل کدهای زیر را قرار میدهیم:
<template>
<div>
<div class="col-md-9" align="center">
<div class="panel-heading">
<div>
<label>Please login through SPA Client</label>
</div>
<div>
<button type="button" @click="login" class="btn btn-primary">Login with SPA client</button>
</div>
</div>
</div>
<div id="app">
{{ message }}
</div>
</div>
</template>
// …
در تگ script آن نیز کدهای زیر را مینویسیم:
<script>
export default {
data() {
return {
message: '',
}
},
methods: {
login() {
const url = 'http://localhost:8000/oauth/token';
const formData = {
grant_type: 'password',
client_id: 4,
client_secret: 'TbOwnj795BvozpYdmlODPLjQCP27wslD7PEtVSpm',
username: 'test@gmail.com',
password: '123456789',
scope: '',
};
const headers = {
'Access-Control-Allow-Origin': '*',
Accept: '*/*',
'Content-Type': 'application/json'
};
axios({
json: true,
method: 'POST',
url: url,
data: formData,
headers: headers,
})
.then(response => (this.message = response.data))
.catch(function (response) {
//handle error
console.log(response);
});
}
}
}
</script>
در کدهای نوشته شده مربوط به تگ script، یک درخواست post با axios نوشته شده است. در این درخواست مقادیر مربوط به کلاینتی که از نوع password grant میباشد را قرار دادهایم. در حقیقت ما با استفاده از vue یک کلاینت روی سرور todo ایجاد کردهایم تا درخواست Password Grant Token خود را با آن ایجاد کنیم.
برای ثبت این کامپوننت جدید فایل resources/js/app.js/ را باز کرده و کد زیر را در آن مینویسیم:
// …
Vue.component('task', require('./components/Client.vue').default);
// …
همانطور که در تکه کد بالا مشاهده میکنید، نام task را برای کامپوننت Client.vue در نظر گرفتهایم. در این مرحله فایل home.blade.php از مسیر /resources/views/home.blade.php را باز کرده و کد زیر را جایگزن کد های آن میکنیم:
@extends('layouts.app')
@section('content')
<task></task>
@endsection
در حقیقت ما بر اساس نامی که برای کامپوننت خود در نظر گرفتیم، به صورت تگ در صفحه مورد نظر خود استفاده نمودیم.
حال فایل routes/web.php/ را باز کرده و مسیر زیر را اضافه میکنیم. این مسیر تنها برای نشان داده صفحه جدید بوده تا بتوانیم بر اساس آن، تست خود را انجام دهیم:
// …
Route::get('/client', function () {
return view('home');
});
// …
و دستورات زیر را اجرا میکنیم:
npm run dev
php artisan serve
در انتها برای مشاهده صفحه جدید مسیر http://localhost:8000/client
را در مرورگر باز میکنیم. شکل زیر، صفحه کلاینت ما را نشان میدهد:
همانطور که مشاهده میشود یک کلید در این صفحه وجود دارد که ما درخواست password grant خود را در رویداد کلیک آن در اسکریپت فایل vue نوشتهایم.
درخواست Access Token
پس از ایجاد کلاینت password grant، میتوانیم با ارسال درخواست POST به مسیر oauth/token/ با آدرس ایمیل و رمز عبور کاربر، access token را درخواست کنیم. ما درخواست POST خود را در بخشهای قبل ایجاد کرده بودیم. برای تست کافی است بر روی کلید مورد نظر کلیک کنیم.
در صورت موفقیت آمیز بودن درخواست، سرور در پاسخ یک access_token و refresh_tokenرا به صورت JSON به ما میدهد که در همان صفحه client به ما نشان میدهد(شکل زیر). علاوه بر مقادیر ذکر شده، تاریخ expire توکن نیز در پاسخ وجود دارد:
نکته: به یاد داشته باشید، به طور پیشفرض عمرaccess token ها طولانی مدت هستند. اما، در صورت نیاز میتوانیم حداکثر طول عمر access token خود را تنظیم کنیم که این مورد در مباحث پیشرفته ذکر خواهد شد.
در این فصل به بررسی یکی دیگر از روش های OAuth با نام Password Grant Token پرداخته و به صورت عملی نحوه کار آن را به شما نشان دادیم. همانطور که در ابتدای فصل مشاهده کردید، Laravel Passport همانند روش قبلی یعنی PKCE، این امکان را در اختیار ما قرار میدهد تا به راحتی بتوانیم کلاینت هایی از این نوع را ایجاد و از آنها استفاده نماییم. در ادامه این آموزش همراه ما باشید.