lifewind/laravel-sso-client

Laravel SSO client for LifeWind authentication

Installs: 0

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/lifewind/laravel-sso-client

v1.0.0 2026-02-09 20:56 UTC

This package is auto-updated.

Last update: 2026-02-09 21:35:49 UTC


README

API-only SSO authentication for Laravel backends.

This package provides secure JWT-based authentication endpoints for validating OAuth tokens from frontend applications.

๐ŸŒŸ Features

  • โœ… API-Only Architecture: Pure JSON endpoints, no redirects
  • โœ… JWT Authentication: Secure token-based authentication
  • โœ… OAuth 2.0 Flow: Industry standard OAuth implementation
  • โœ… User Management: Automatic user creation and updates
  • โœ… CORS Ready: Cross-domain frontend support
  • โœ… Frontend Agnostic: Works with Vue, React, Angular, or any frontend

๐Ÿ“‹ Prerequisites: Register Your App in LifeWind Core

Before installing this package, you need an OAuth client registered in LifeWind Core:

  1. Login to the LifeWind Core admin panel at https://lifewind-core.test/admin (or your production URL)
  2. Navigate to OAuth Clients โ†’ Create Client
  3. Fill in:
    • Name: Your app name (e.g. "Atlas")
    • Redirect URI: Your frontend callback URL (e.g. https://your-app.com/sso/callback)
    • Grant Type: Authorization Code
  4. After creation, copy the Client ID and Client Secret โ€” you'll need these for your .env

Tip: For local development, use http://localhost:3001/sso/callback as the redirect URI (adjust port to match your frontend dev server).

๐Ÿš€ Quick Start

1. Installation

composer require lifewind/laravel-sso-client

2. Configuration

Publish configuration and run migrations:

php artisan vendor:publish --provider="LifeWind\SSO\SSOServiceProvider"
php artisan migrate

3. Environment Setup

# LifeWind SSO Configuration
LIFEWIND_SSO_BASE_URL=https://lifewind-core.your-domain.com
LIFEWIND_SSO_CLIENT_ID=your_oauth_client_id
LIFEWIND_SSO_CLIENT_SECRET=your_oauth_client_secret
LIFEWIND_SSO_REDIRECT_URI=https://your-frontend.com/sso/callback
LIFEWIND_SSO_CREATE_USERS=true
LIFEWIND_SSO_UPDATE_USERS=true

# JWT Configuration
LIFEWIND_SSO_JWT_SECRET=your-256-bit-secret-key
LIFEWIND_SSO_JWT_EXPIRY=86400

4. CORS Configuration

Update config/cors.php:

return [
    'paths' => ['api/*', 'sso/*'],
    'allowed_origins' => ['https://your-frontend.com'],
    'allowed_headers' => ['*'],
    'allowed_methods' => ['*'],
    'supports_credentials' => false, // JWT in Authorization header
];

๐Ÿ“ก API Endpoints

The package automatically registers these endpoints:

Method Endpoint Description
POST /sso/validate Validate OAuth code โ†’ return JWT + user
GET /sso/user Get authenticated user (Bearer token)
POST /sso/refresh Refresh JWT token

POST /sso/validate

Exchange OAuth authorization code for JWT token.

Request:

{
  "code": "oauth_authorization_code_from_callback",
  "state": "oauth_state_parameter",
  "redirect_uri": "https://your-frontend.com/sso/callback"
}

Success Response (200):

{
  "success": true,
  "user": {
    "id": 1,
    "email": "user@example.com",
    "name": "John Doe",
    "lifewind_uuid": "550e8400-e29b-41d4-a716-446655440000"
  },
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
  "expires_in": 86400
}

Error Response (400):

{
  "success": false,
  "error": "Token validation failed: Invalid authorization code"
}

GET /sso/user

Get current authenticated user information.

Headers:

Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
Accept: application/json

Success Response (200):

{
  "authenticated": true,
  "local_user": {
    "id": 1,
    "email": "user@example.com",
    "name": "John Doe",
    "lifewind_uuid": "550e8400-e29b-41d4-a716-446655440000"
  },
  "authenticated_via": "jwt",
  "token_expiry": "2024-01-15T14:30:00.000Z"
}

Error Response (401):

{
  "error": "Invalid or expired authentication token",
  "authenticated": false
}

POST /sso/refresh

Refresh an existing JWT token.

Headers:

Authorization: Bearer current_jwt_token
Accept: application/json

Success Response (200):

{
  "success": true,
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
  "expires_in": 86400,
  "token_expiry": "2024-01-16T14:30:00.000Z"
}

๐Ÿ”’ Protecting Routes

Use the built-in middleware to protect your API routes:

// routes/api.php
Route::middleware(['lifewind.auth'])->group(function () {
    Route::get('/dashboard', [DashboardController::class, 'index']);
    Route::apiResource('projects', ProjectController::class);
    Route::get('/profile', [UserController::class, 'profile']);
});

๐Ÿ› ๏ธ Using in Controllers

Access the authenticated user in your controllers:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;

class DashboardController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        // The middleware ensures this user is authenticated
        $user = $request->user(); // Returns User model instance
        
        return response()->json([
            'message' => "Welcome {$user->name}!",
            'user' => [
                'id' => $user->id,
                'email' => $user->email,
                'name' => $user->name,
                'lifewind_uuid' => $user->lifewind_uuid,
            ],
            'dashboard_data' => [
                'recent_activity' => '...',
                'notifications' => '...'
            ]
        ]);
    }
}

๐Ÿ”ง Advanced Configuration

Custom User Model

If you're using a custom User model:

// config/lifewind-sso.php
'user' => [
    'model' => App\Models\CustomUser::class,
    'create' => true,
    'update' => true,
    'fields' => [
        'email' => 'email',
        'name' => 'name',
        'lifewind_uuid' => 'lifewind_uuid',
    ],
],

JWT Configuration

# JWT Settings
LIFEWIND_SSO_JWT_SECRET=your-super-secure-256-bit-secret-key
LIFEWIND_SSO_JWT_EXPIRY=86400                    # 24 hours in seconds
LIFEWIND_SSO_JWT_ALGORITHM=HS256                 # Signing algorithm

OAuth Scopes

# Request specific scopes from LifeWind
LIFEWIND_SSO_SCOPES="openid,profile,email,roles"

Database Configuration

# User creation/update behavior
LIFEWIND_SSO_CREATE_USERS=true    # Create new users automatically
LIFEWIND_SSO_UPDATE_USERS=true    # Update existing users from SSO data

๐Ÿงช Testing & Debugging

Test Command

# Test SSO configuration
php artisan sso:test

# Test with detailed output
php artisan sso:test --verbose

# Test specific environment
php artisan sso:test --env=staging

Manual Testing

Test the endpoints manually:

# 1. Test validation endpoint
curl -X POST https://your-backend.com/sso/validate \
  -H "Content-Type: application/json" \
  -d '{
    "code": "test_auth_code",
    "state": "test_state",
    "redirect_uri": "https://your-frontend.com/sso/callback"
  }'

# 2. Test user endpoint with returned token
curl -X GET https://your-backend.com/sso/user \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Accept: application/json"

๐ŸŒ Frontend Integration

This package is designed for frontend-initiated OAuth flows:

Flow Overview

  1. Frontend redirects user to LifeWind OAuth provider
  2. LifeWind authenticates user and redirects back to frontend
  3. Frontend captures authorization code from callback URL
  4. Frontend sends code to your backend's /sso/validate endpoint
  5. Backend validates code with LifeWind and returns JWT + user data
  6. Frontend stores JWT token for subsequent API requests

For Vue.js Applications

Use our companion Vue.js package:

npm install lifewind-vue-sso-client
<template>
  <LifeWindSSOButton 
    @success="handleAuth"
    button-text="Login with LifeWind"
  />
</template>

<script setup>
import { LifeWindSSOButton } from 'lifewind-vue-sso-client'

const handleAuth = (result) => {
  console.log('Authenticated:', result.user)
  // Token automatically stored, ready for API calls
}
</script>

For Other Frontends

Implement the OAuth flow manually:

// 1. Redirect to OAuth provider
const authUrl = `https://lifewind-core.com/oauth/authorize?` + 
  `client_id=YOUR_CLIENT_ID&` +
  `redirect_uri=${encodeURIComponent('https://your-frontend.com/callback')}&` +
  `response_type=code&` +
  `state=${generateRandomState()}&` +
  `scope=openid profile email`

window.location.href = authUrl

// 2. Handle callback (in your callback page)
const urlParams = new URLSearchParams(window.location.search)
const code = urlParams.get('code')
const state = urlParams.get('state')

// 3. Validate with your backend
const response = await fetch('https://your-backend.com/sso/validate', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    code,
    state,
    redirect_uri: 'https://your-frontend.com/callback'
  })
})

const result = await response.json()

if (result.success) {
  // Store JWT token for API requests
  localStorage.setItem('auth_token', result.token)
  localStorage.setItem('user', JSON.stringify(result.user))
}

๐Ÿšจ Production Checklist

Security Requirements

  • HTTPS Only: Both frontend and backend must use HTTPS
  • Strong JWT Secret: Use a secure 256-bit random key
  • CORS Origins: Only allow your actual frontend domains
  • Environment Variables: All secrets properly configured
  • SSL Verification: Enable SSL verification for OAuth requests

Example Production Configuration

# Production Environment
APP_ENV=production
APP_DEBUG=false
APP_URL=https://api.your-domain.com

# LifeWind SSO (Production)
LIFEWIND_SSO_BASE_URL=https://sso.lifewind.com
LIFEWIND_SSO_CLIENT_ID=prod_client_id_here
LIFEWIND_SSO_CLIENT_SECRET=prod_client_secret_here
LIFEWIND_SSO_REDIRECT_URI=https://app.your-domain.com/sso/callback
LIFEWIND_SSO_JWT_SECRET=your-production-256-bit-secret-key
LIFEWIND_SSO_VERIFY_SSL=true

# Remove all localhost/development origins from CORS!

Performance Optimization

// config/lifewind-sso.php
'cache' => [
    'user_data' => true,      // Cache user data lookups
    'ttl' => 300,             // 5 minutes
],

'rate_limiting' => [
    'validate' => '10,1',     // 10 requests per minute
    'user' => '60,1',         // 60 requests per minute
    'refresh' => '5,1',       // 5 requests per minute
],

๐Ÿ“‹ Troubleshooting

Common Issues

"Invalid authorization code" error:

  • Check that LIFEWIND_SSO_REDIRECT_URI matches exactly what you registered
  • Ensure the authorization code hasn't expired (usually 10 minutes)
  • Verify the redirect_uri sent to /sso/validate matches OAuth registration

CORS errors:

  • Add your frontend domain to config/cors.php
  • Ensure Access-Control-Allow-Credentials is properly configured
  • Check that preflight OPTIONS requests are handled

JWT token invalid:

  • Verify LIFEWIND_SSO_JWT_SECRET is the same across all app instances
  • Check token hasn't expired (expires_in seconds)
  • Ensure Bearer token format: Authorization: Bearer <token>

Debug Logging

Enable detailed logging in development:

LOG_LEVEL=debug
LIFEWIND_SSO_DEBUG=true

Check logs at:

tail -f storage/logs/laravel.log | grep SSO

๐Ÿ“„ License

MIT License. See LICENSE for details.

๐Ÿค Support

Built for modern API-first applications ๐Ÿš€