Прийдіть за простотою, залиштеся за розширюваністю: ідентифікація з FusionAuth

Перекладено ШІ
Оригінал: Laravel News
Оновлено: 25 березня, 2025
Як розробник, безпека мого застосунку є пріоритетом. Чи знаєте ви, як інтегрувати FusionAuth у Laravel, щоб підвищити безпеку ваших додатків? У цій статті я покажу, як це зробити на прикладі реального проекту, розгорнутого в AWS

Для розробників безпека додатків і API є одним із найважливіших аспектів. Проте часто про це починають думати надто пізно в процесі проєктування, або ж змушені використовувати застарілі рішення, приймаючи неприємні для себе рішення. Саме тому я постійно запитую себе: чи є альтернативні способи розв'язання поширених проблем, щоб зробити мої рішення більш стійкими та розширювальними, враховуючи постійно змінювані потреби користувачів? У світі PHP і Laravel це питання завжди актуальне, а FusionAuth пропонує саме те, що потрібно для автентифікації.

У цій статті я на прикладі покажу, як використати FusionAuth у Laravel-додатку, розгорнутому на Elastic Container Service AWS за допомогою Cloud Development Kit.

# Розкриття інформації

Перед початком зазначу, що FusionAuth спонсорував мене для експериментів із їхнім продуктом та звіту про результати. Вони отримали мою увагу, проте не мою думку. Ось мій неупереджений погляд на досвід розробника при створенні Laravel-додатку з використанням FusionAuth для автентифікації.

# Огляд рішення

Розпочинаючи з прикладів рішень, я завжди віддаю перевагу починати з кінцевого результату і лише потім рухатись назад. Це стосується не лише написання статті, а й формування структури, яку я хочу презентувати. Я віддаю перевагу AWS, оскільки маю понад 10 років досвіду роботи на їхній платформі. Проте, краще один раз побачити, ніж сто разів почути.

У цій архітектурній схемі ключові компоненти такі:

З дизайном готово, давайте поглянемо на рішення по порядку!

# Процес виконання рішення

Я швидко пройдуся по налаштуванню додатку та структурі проєкту, оскільки хочу більше зосередитися на Socialite, налаштуванні FusionAuth і розгортанні на AWS.

# Налаштування Laravel-додатку

Я не робив нічого особливого при створенні Laravel-додатку. Все розпочалося з команди:

laravel new fusionauth-app

Надалі я відповів на запитання налаштування, обравши PHPUnit для тестування, SQLite для бази даних і Vite для фронтенд-інструментів. Ця конфігурація створила структуру проєкту з відповідними каталогами та файлами.

Тепер можемо додати Socialite.

# Laravel Socialite з FusionAuth

Socialite дозволяє легко інтегрувати OAuth-автентифікацію з різними провайдерами, такими як Facebook, GitHub та інші. Він обробляє більшість рутинного коду, якого багато хто з нас хоче уникнути. За допомогою Socialite я можу аутентифікувати користувачів через різних провайдерів, включаючи FusionAuth. Це дає можливість обмежувати доступ до мого додатку.

Щоб підключити FusionAuth, виконайте наступні кроки.

Крок 1: Додати Socialite до проєкту.

# Додаємо залежність Socialite
composer require laravel/socialite
# Додаємо провайдер FusionAuth
composer require socialiteproviders/fusionauth

Крок 2: Встановити змінні середовища в файлі .env та надати значення у config/services.php.

# .env файл
# Налаштування FusionAuth
FUSIONAUTH_CLIENT_ID=
FUSIONAUTH_CLIENT_SECRET=<Секрет клієнта FusionAuth>
FUSIONAUTH_BASE_URL=<Базовий URL FusionAuth>
FUSIONAUTH_TENANT_ID=
FUSIONAUTH_REDIRECT_URI=

Ці змінні потім використовуються в services.php для налаштування провайдера Socialite FusionAuth.

return [
    'fusionauth' => [
        'client_id' => env('FUSIONAUTH_CLIENT_ID'),
        'client_secret' => env('FUSIONAUTH_CLIENT_SECRET'),
        'redirect' => env('FUSIONAUTH_REDIRECT_URI'),
        'base_url' => env('FUSIONAUTH_BASE_URL'),
        'tenant_id' => env('FUSIONAUTH_TENANT_ID'),
    ]
];

Крок 3: Створити маршрути для перенаправлення користувача до FusionAuth та обробки зворотного зв'язку. Потрібен Controller з двома функціями.

Перша функція, redirectToFusionAuth, виконує перенаправлення до FusionAuth. Друга функція, callbackFusionAuth, обробляє повернення з FusionAuth, отримуючи дані користувача та зберігаючи їх у локальній таблиці SQLite.

<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Laravel\Socialite\Facades\Socialite;

class FusionAuthLoginController extends Controller
{
    public function redirectToFusionAuth()
    {
        return Socialite::driver('fusionauth')->redirect();
    }

    public function callbackFusionAuth()
    {
        $user = Socialite::driver('fusionauth')->user();
        $user = User::updateOrCreate([
            'fusionauth_id' => $user->id,
        ], [
            'name' => $user->name,
            'email' => $user->email,
            'given_name' => $user->user['given_name'],
            'family_name' => $user->user['family_name'],
            'fusionauth_access_token' => $user->token,
        ]);
        Auth::login($user);

        return redirect('/profile');
    }
}

Для довідки, ось мій клас User.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use HasFactory;

    protected $fillable = [
        'name',
        'email',
        'given_name',
        'family_name',
        'fusionauth_id',
        'fusionauth_access_token',
    ];

    protected $hidden = ['password', 'remember_token'];
}

Після того, як користувач увійшов, я можу використовувати перевірку доступу на рівні сторінки або API, щоб контролювати виконання операцій. Це робиться традиційним способом у Laravel за допомогою Gates або Policies.

Отже, у мене вже є Laravel-додаток з установленим плагіном Socialite, який успішно пов'язаний з FusionAuth. Тепер привернемо увагу до FusionAuth.

# FusionAuth (Хостинг)

FusionAuth можна використовувати як на власних серверах, так і на їхньому хостингу. Вони пропонують безліч рішень. Я вирішив зосередитися на розробницькому досвіді з FusionAuth, тому скористався їхнім хостингом.

FusionAuth — це повноцінний постачальник OAuth 2.0 та OIDC. Ці два поняття часто плутають, але вони різні: OAuth 2.0 використовується для авторизації, а OIDC — для аутентифікації.

Це головний екран програми в FusionAuth, де я налаштував свій Laravel-додаток, зазначивши необхідні налаштування, включаючи Authorized Redirect URLs.

Тут ви знайдете знайомі налаштування для OAuth та OIDC. Ось швидкий огляд!

Ключові кінцеві точки

Обсяги

FusionAuth пропонує багато можливостей для налаштувань, включаючи кастомізацію JWT, а також інтеграцію SAML та можливість самостійної реєстрації користувачів.

Я не можу охопити всі можливості, які доступні в меню з навігацією, але хочу виділити звітність. Я часто отримую запитання на кшталт "Скільки активних користувачів у нас?" або "Скільки було реєстрацій цього місяця?" FusionAuth має для цього розділ звітів.

Отже, у мене вже розгорнута FusionAuth та Laravel-додаток, зв’язаний із FusionAuth через Socialite. Залишилося розгорнути додаток на AWS.

# AWS та CDK

Мій Laravel-додаток працює в AWS. Я трохи налаштував стартову сторінку, і тепер вона запущена під HTTPS на Elastic Container Service (ECS) AWS. Це означає, що я упакував його в Docker-контейнер. Чи використовував я Sail? CloudFormation? Давайте дізнаємось!

# Чому CDK

Існує безліч варіантів для розгортання інфраструктури та додатків в AWS. Я міг би використовувати CloudFormation, Terraform або Pulumi, але обрав AWS Cloud Development Kit (CDK) — зазвичай на TypeScript.

CDK дозволяє створювати класи, які відображають представлення CloudFormation, і я звик до його документації, завдяки чому все виглядає зрозуміло і знайоме на ділянці інфраструктури.

# Процес розгортання

Згадаймо архітектуру рішення. Потрібно створити публічні та приватні мережі, віртуальні приватні хмари, баланси навантаження, кластер ECS і так далі.

- app-infra/
- infra/

Директорія infra містить базові ресурси — усю інфраструктуру поза Fargate. Кожен зі створюваних ресурсів підтримує розгортання Laravel-додатку.

Наприклад, створення ECS кластера виглядає так:

let cluster = new Cluster(
  scope,
  `EcsCluster`,
  {
    clusterName: `DemoCluster`,
    vpc: props.vpc
  }
);

Повний робочий приклад доступний на GitHub у кінці статті. Однак важливо зазначити, що для хостингу додатку в AWS ECS залучені такі сервіси:

Для всього цього потрібно повернутись до Laravel-додатку. Як я вже згадував, програма упакована в Docker-контейнер з Nginx у ролі зворотного проксі, який належно обробляє статичний контент. У каталозі проєкту знаходиться docker/ з entrypoint.sh, що запускає Nginx та PHP.

#!/usr/bin/env bash

service nginx start
php artisan migrate --force
php artisan storage:link
php artisan optimize:clear
php artisan optimize
php-fpm

Там є ще default.conf, що містить конфігураційні параметри для Nginx.

server {
    listen 80 default_server;
    server_name localhost;
    root /var/www/public;

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;

        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
 
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
}

CloudFormation в AWS розглядає деплойменти як "Stacks", що містять ресурси для розгортання. Кожна з директорій при створенні свого стеку має власні ресурси для керування. Розгортання відбувається на простому за допомогою:

cd infra
cdk deploy
#
cd ../app-infra
cdk deploy

# Остаточний продукт

Це був насичений огляд Laravel та Socialite, FusionAuth і AWS CDK. Але що в результаті всіх цих зусиль? У мене тепер є додаток, що завантажується з ECS, автентифікує користувача за допомогою FusionAuth і показує просту сторінку профілю з даними, які зберігаються в FusionAuth. Ця інформація містить мою електронну пошту, дату народження, ім'я, прізвище, а також не відображувану часову зону.

При переході до свого додатку я можу натиснути "Увійти" у верхньому правому куті, і мене перенаправить на сторінку для введення облікових даних.

Після успішної верифікації я потраплю на сторінку профілю, де бачу свої дані.

# Враження та висновки

Аутентифікація та авторизація рідко бувають привабливими аспектами рішень. Коли щось йде не так, це швидше привабливе іншим, а не дизайнерським. Тому я шукаю рішення, яке є надійним, гнучким і розширювальним. Хоча я ще не тестував FusionAuth у продуктивному масштабі, сподіваюся, ви зрозуміли з цієї статті, що воно дуже налаштоване та розширюване. Я також помітив, що модель ціноутворення FusionAuth є привабливою, а підтримка відповідає потребам, чи це цілодобовий сервіс, чи внутрішній проєкт протягом робочого часу.

# Плюси

Мені сподобалася гнучкість у налаштуванні. Досвід адміністратора виявився корисним, всі потрібні мені налаштування на місці. Інтеграція з PHP та Laravel була надзвичайно простою. Я просто підключив Socialite, встановив змінні, написав невеликий Controller — і все запрацювало.

Також варто відзначити надзвичайну документацію, яка допомогла мені швидко освоїти FusionAuth та зрозуміти концепції, пов'язані з розгортанням.

# Але є над чим попрацювати

Це радше загальна проблема, ніж конкретна для FusionAuth. Коли я думаю про PHP-додатки, не уявляю собі контейнеризацію чи Kubernetes. Я б вважав за краще налаштувати функціонал на рівні одного застосунку. Документація FusionAuth чудова, але я не зумів реалізувати налаштування самостійно. Тому я вирішив скористатися їхнім хостингом, щоб зосередитися на розробці, а не на налаштуваннях інфраструктури.

Можливо, якби були шаблони для швидкого розгортання в AWS з попередніми налаштуваннями, це б пришвидшило процес.

# Висновок

Створення власної автентифікації не є рішучим кроком у наші часи. Якщо ви плануєте розширення, вам точно варто інвестувати в рішення третіх осіб. У цьому сегменті є конкуренція, проте мій досвід з FusionAuth під час написання статті переконує мене, що, якби я створював новий проєкт, звернувся б до FusionAuth.

Цей продукт легко управляти, має велику налаштованість та безліч можливостей для розширення. Коли я працюю з Laravel, інтеграція з Socialite проходить стає простою. Паралельно з AWS я впевнений, що FusionAuth стане надійним і потужним інструментом для моїх проєктів.

Я посилався на безліч коду, тому ось репозиторій GitHub, який ви можете клонувати, побудувати та розгорнути самостійно.

Дякую за увагу та успіхів у розробці!