Vue.js + Laravel API
Split your app into a Vue SPA frontend and a Laravel API backend. Laravel handles OAuth with WamISSO; Vue consumes authenticated API routes via Sanctum session cookies or API tokens.
Before you start:
Complete developer registration and create an OAuth client.
Register two redirect URIs if needed:
http://localhost:5173/auth/callback (Vue) or handle callback on the API at
http://localhost:8001/api/auth/sso/callback.
Recommended architecture
Laravel API setup
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
# API .env
SSO_BASE_URL=https://wamisso.rendovations.com
SSO_CLIENT_ID=your-client-id
SSO_CLIENT_SECRET=your-client-secret
SSO_REDIRECT_URI=http://localhost:8001/api/auth/sso/callback
FRONTEND_URL=http://localhost:5173
SANCTUM_STATEFUL_DOMAINS=localhost:5173
SESSION_DOMAIN=localhost
API routes
// routes/api.php
use App\Http\Controllers\Api\SsoAuthController;
Route::prefix('auth/sso')->group(function () {
Route::get('/redirect', [SsoAuthController::class, 'redirect']);
Route::get('/callback', [SsoAuthController::class, 'callback']);
});
Route::middleware('auth:sanctum')->group(function () {
Route::get('/user', fn (Request $request) => $request->user());
Route::post('/logout', [SsoAuthController::class, 'logout']);
});
SSO auth controller
// app/Http/Controllers/Api/SsoAuthController.php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
class SsoAuthController extends Controller
{
public function redirect(): JsonResponse
{
$state = Str::random(40);
session(['oauth_state' => $state]);
$query = http_build_query([
'client_id' => config('services.wamisso.client_id'),
'redirect_uri' => config('services.wamisso.redirect'),
'response_type' => 'code',
'scope' => 'openid profile email',
'state' => $state,
]);
return response()->json([
'authorize_url' => config('services.wamisso.base_url').'/oauth/authorize?'.$query,
]);
}
public function callback(Request $request): RedirectResponse
{
if ($request->query('state') !== session('oauth_state')) {
abort(403, 'Invalid OAuth state');
}
session()->forget('oauth_state');
$tokens = Http::asForm()
->post(config('services.wamisso.base_url').'/oauth/token', [
'grant_type' => 'authorization_code',
'client_id' => config('services.wamisso.client_id'),
'client_secret' => config('services.wamisso.client_secret'),
'redirect_uri' => config('services.wamisso.redirect'),
'code' => $request->query('code'),
])
->throw()
->json();
$profile = Http::withToken($tokens['access_token'])
->get(config('services.wamisso.base_url').'/api/user')
->throw()
->json();
$user = User::query()->updateOrCreate(
['email' => $profile['email']],
['name' => $profile['name'] ?? $profile['email']],
);
Auth::login($user);
return redirect(config('app.frontend_url', env('FRONTEND_URL')).'/dashboard');
}
public function logout(Request $request): JsonResponse
{
$accessToken = session('sso_access_token');
if ($accessToken) {
Http::withToken($accessToken)
->post(config('services.wamisso.base_url').'/api/sso/logout');
}
Auth::guard('web')->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return response()->json(['status' => 'logged_out']);
}
}
CORS and Sanctum
// config/cors.php
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'supports_credentials' => true,
'allowed_origins' => [env('FRONTEND_URL', 'http://localhost:5173')],
Vue login composable
// src/composables/useAuth.js
import axios from 'axios';
axios.defaults.withCredentials = true;
axios.defaults.baseURL = import.meta.env.VITE_API_URL; // http://localhost:8001
export async function loginWithSso() {
await axios.get('/sanctum/csrf-cookie');
const { data } = await axios.get('/api/auth/sso/redirect');
window.location.href = data.authorize_url;
}
export async function fetchUser() {
const { data } = await axios.get('/api/user');
return data;
}
export async function logout() {
await axios.post('/api/logout');
}
Vue login page
<script setup>
import { loginWithSso } from '@/composables/useAuth';
</script>
<template>
<div class="login">
<h1>Sign in</h1>
<button type="button" @click="loginWithSso">
Continue with WamISSO
</button>
</div>
</template>
Enable
withCredentials on Axios/fetch so Sanctum session cookies work across your Vue app and Laravel API during local development.