Application Portal Documentation

Part 1: USER GUIDE - Application Portal


Table of Contents


1. Overview

The Application Portal is a central hub that connects you to other company systems and services. Think of it as an app launcher for all your work tools.

What is This Portal?

It's a dashboard displaying all available applications and systems that you can access using your DTR account. No need to remember multiple passwords!

Key Features

Single Sign-On (SSO) - Login once, access multiple systems
App Launcher - Quick access to all connected applications
Seamless Integration - Your DTR credentials work everywhere
Secure Authentication - Encrypted token-based access
Direct Links - Browse applications without logging in

What Apps Are Available?

Depending on your organization, available applications might include:

📊 HR Management System
💼 Project Management Tool
📧 Email & Communication
📁 Document Management
💰 Payroll System
📈 Analytics Dashboard
🏢 Intranet Portal
👥 Employee Directory

2. Getting Started

2.1 Access the Portal

Option 1: From Home

Login to DTR System
    ↓
Click "Apps" button (top navigation)
    ↓
Application Portal Opens

Option 2: Direct URL

Navigate to: https://dtr.company.com/apps

Option 3: Navigation Menu

Top-right Menu → Applications → Click

2.2 Portal Layout

┌─────────────────────────────────────────────────────────┐
│                   APPLICATION PORTAL                    │
├─────────────────────────────────────────────────────────┤
│                                                         │
│ ⚠️  BETA NOTE: Features may change                      │
│                                                         │
│   APPS GRID (6-column layout)                          │
│   ┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐   │
│   │ Home │  │ App1 │  │ App2 │  │ App3 │  │ App4 │   │
│   │ 🏠   │  │ 📊   │  │ 💼   │  │ 📧   │  │ 📁   │   │
│   └──────┘  └──────┘  └──────┘  └──────┘  └──────┘   │
│                                                         │
│   ┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐   │
│   │ App5 │  │ App6 │  │ App7 │  │ App8 │  │ App9 │   │
│   │ 💰   │  │ 📈   │  │ 🏢   │  │ 👥   │  │ 🎯   │   │
│   └──────┘  └──────┘  └──────┘  └──────┘  └──────┘   │
│                                                         │
│   (Scrollable to see more apps)                        │
│                                                         │
└─────────────────────────────────────────────────────────┘

2.3 Understanding the Interface

App Card

┌──────────────┐
│   [ICON]     │  ← App icon image (if available)
│   App Name   │  ← Application name
└──────────────┘
     ▲
  Hover effect:
  - Lifts up slightly
  - Shadow increases
  - Indicates clickable

Home Button

┌──────────────┐
│   [HOME]     │  ← Links to DTR Dashboard
│   Home       │
└──────────────┘

3. Application Launcher

3.1 Launch an Application

Step 1: Find the App

Scroll through the grid to find the application you need.

Examples:

🏢 HR System      - Employee records and benefits
💼 Project Tools  - Task management and collaboration
📊 Analytics      - Reports and dashboards
📧 Communication  - Email and messaging
💰 Payroll        - Salary and compensation info

Step 2: Click the App

Click on any app card to open its details modal.

[Click] → Modal Opens ↓

Step 3: Modal Details

┌──────────────────────────────────────┐
│        APPLICATION DETAILS           │
├──────────────────────────────────────┤
│                                      │
│              [APP ICON]              │
│                                      │
│          Application Name            │
│                                      │
│  ┌─────────────────────────────────┐│
│  │ [Login (SSO)]  [View Page]      ││
│  └─────────────────────────────────┘│
│                                      │
│  [X] Close Button                    │
│                                      │
└──────────────────────────────────────┘

3.2 Available Actions

Each application modal has up to 2 buttons:

Button When Available Action
Login (SSO) If SSO enabled Auto-login with your DTR account
View Page Always Opens app in new window

4. SSO Login (Single Sign-On)

4.1 What is SSO?

SSO (Single Sign-On) allows you to:

  • ✅ Use your DTR login credentials for other apps
  • ✅ Skip entering passwords multiple times
  • ✅ Access secured applications instantly
  • ✅ Maintain security with encrypted tokens

4.2 How SSO Works

You Click [Login (SSO)]
    ↓
System Creates Secure Token
    ├─ Your User ID
    ├─ Email
    ├─ Name & Roles
    └─ Expiry Time (60 minutes)
    ↓
Token Gets Encrypted
    ├─ Uses app's secret key
    ├─ Impossible to modify
    └─ Timestamped
    ↓
You're Redirected to App
    ├─ Browser opens new window
    ├─ Token sent in URL
    └─ App verifies token
    ↓
App Authenticates You
    ├─ Validates your identity
    ├─ Creates session
    ├─ Logs you in automatically
    └─ No password needed!
    ↓
✅ You're Logged In!

4.3 SSO Login Process

Step 1: Find App with SSO

Look for apps with blue button:

┌──────────────────────────────┐
│ [Login (SSO)]   ← Blue button │
│ [View Page]     ← Gray button  │
└──────────────────────────────┘

Step 2: Click "Login (SSO)"

[Login (SSO)] ← Click here
    ↓
Processing...

Step 3: Wait for Redirect

┌──────────────────────────────┐
│  🔄 AUTHENTICATING...        │
│                              │
│  Please wait while we log    │
│  you into the application.   │
│                              │
└──────────────────────────────┘

Step 4: App Opens in New Window

✅ New Tab: [Application Name]
   Your account: juan@company.com
   Status: ✅ Logged In

You're now authenticated and can use the application!

4.4 SSO Security Features

Why is SSO Secure?

Encrypted Token - Cannot be read or modified
Time Limit - Token expires after 60 minutes
Unique Secret - Each app has its own encryption key
No Password Shared - Only identifier is sent
Server Verification - App verifies token validity

Example Token (Encrypted):

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
[Impossible to read without the secret key]

4.5 What Information is Sent?

When you use SSO, the app receives:

{
    "app_id": 1,
    "user_id": 5,
    "email": "juan.delacruz@company.com",
    "name": "Juan Dela Cruz",
    "roles": ["employee", "team-lead"],
    "expiry": 1733347200
}

Note: Your password is NEVER sent to other applications!


5. Direct Access (Without SSO)

5.1 View Page Button

If you want to access an app without automatic login:

┌──────────────────────────────┐
│ [Login (SSO)]                │
│ [View Page]   ← Click here   │
└──────────────────────────────┘

5.2 What Happens

  1. Click [View Page]
  2. New browser tab opens
  3. App's home page displays
  4. You may need to login manually
  5. Use your credentials if required

When to Use This:

  • ✅ If SSO is not available
  • ✅ If you're having SSO issues
  • ✅ To just browse without logging in
  • ✅ To access from external network

6. Troubleshooting

Issue 1: "No SSO Button (Login)"

Symptom: Only "View Page" button shows, no "Login (SSO)"

Reason: SSO is not enabled for that application

Solution:

  1. Use "View Page" button
  2. Contact app admin if you need SSO
  3. Contact IT if you need SSO enabled

Issue 2: "SSO Login Failed"

Symptom: Error message after clicking SSO button

❌ "Failed to process SSO login: [error]"

Solutions:

  1. Check Internet: Ensure you have connection
  2. Clear Cache: Clear browser cache and try again
  3. Different Browser: Try Chrome, Firefox, Safari
  4. Check DTR Password: Re-login to DTR first
  5. Contact IT: If issue persists

Issue 3: "Token Expired"

Symptom: Error message saying "Token expired"

Reason: Took too long to login (>60 min token)

Solution:

  1. Go back to Application Portal
  2. Click SSO button again
  3. Complete login within 60 minutes

Issue 4: "App Not Loading"

Symptom: Blank page or error after SSO redirect

Solutions:

  1. Wait 5-10 seconds for app to load
  2. Refresh page
  3. Check if app is online (IT support)
  4. Try "View Page" instead

Issue 5: "Permission Denied"

Symptom: Logged in but cannot access app

Reason: Your role doesn't have permission

Solution:

  1. Contact your Team Lead
  2. Request access to application
  3. IT will grant permissions
  4. Try again after 1 hour

FAQ

Q: Why use SSO instead of password?
A: More secure, faster login, no password sharing between apps.

Q: Is my DTR password sent to other apps?
A: No, never. Only a secure encrypted token is sent.

Q: What if I forget the app's password?
A: Use SSO instead! No app password needed.

Q: Can someone else use my SSO token?
A: No, token is encrypted and expires in 60 minutes.

Q: What if I change my DTR password?
A: SSO still works. Token is based on your ID, not password.

Q: Can I logout from all apps at once?
A: No, logout from each app individually or close all tabs.

Q: How many apps can I access?
A: As many as you have permissions for.

Q: Is SSO available on mobile?
A: Yes, same process on phone browsers.


END OF USER GUIDE - PART 1


PART 2: DEVELOPER GUIDE - Application Portal


Table of Contents


1. Architecture

1.1 System Flow

┌─────────────────────────────────────────────────────────┐
│                  DTR MAIN SYSTEM                        │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  User (Authenticated)                                   │
│    ↓                                                    │
│  AppController@apps()                                   │
│    ├─ Fetch all apps from 'clients' table              │
│    └─ Render apps/index.blade.php                      │
│    ↓                                                    │
│  View: apps/index.blade.php                             │
│    ├─ Display app cards                                │
│    ├─ Alpine.js modals                                 │
│    └─ SSO & Direct links                               │
│                                                         │
│  User clicks app → Modal opens                          │
│    ├─ [Login (SSO)] → ApplicationLanding()             │
│    └─ [View Page] → Direct redirect                    │
│    ↓                                                    │
│  AppController@applicatonLanding($appId)               │
│    ├─ Load app config (Client model)                   │
│    ├─ Generate SSO token                               │
│    ├─ Encrypt token with app secret                    │
│    └─ Redirect to external app with token              │
│    ↓                                                    │
│  EXTERNAL APP (HR System, etc)                          │
│    ├─ Receives encrypted token                         │
│    ├─ Decrypts with shared secret                      │
│    ├─ Validates token signature & expiry               │
│    ├─ Creates user session                             │
│    └─ User logged in! ✅                               │
│                                                         │
└─────────────────────────────────────────────────────────┘

1.2 Component Interaction

AppController
    ├── apps() method
    │   ├── Fetch apps from Client model
    │   └── Return to view
    │
    └── applicatonLanding() method
        ├── Get Client by ID
        ├── Create SSO payload
        ├── Encrypt with Encrypter class
        ├── Generate redirect URL
        └── Return redirect response

2. Controller Implementation

2.1 AppController.php

File: app/Http/Controllers/AppController.php

Method: apps()

Purpose: Display all available applications

public function apps()
{
    // Get all apps from Client table
    $apps = Client::all();

    // Return view with apps
    return view('apps.index', compact('apps'));
}

Database Query:

SELECT * FROM clients;

Data Passed to View:

[
    'apps' => [
        Client {
            id: 1,
            name: "HR System",
            client_id: "randomstring1",
            client_secret: "randomstring2",
            redirect_url: "https://hr.company.com",
            is_sso: true,
            icon: Attachment {}
        },
        Client {
            id: 2,
            name: "Project Tools",
            ...
        }
    ]
]

Method: applicatonLanding($appId)

Purpose: Generate SSO token and redirect to external app

public function applicatonLanding($appId)
{
    // 1. Load application config
    $application = Client::where('id', $appId)->first();

    if (!$application) {
        abort(404);  // App not found
    }

    try {
        // 2. Create SSO payload (JWT-like)
        $payload = json_encode([
            'app_id' => $application->id,
            'client_id' => $application->client_id,
            'client_secret' => $application->client_secret,
            'email' => auth()->user()->email,
            'name' => auth()->user()->name,
            'roles' => auth()->user()->roles,
            'user_id' => auth()->user()->id,
            'expiry' => now()->addMinutes(60)->timestamp,
        ]);

        // 3. Encrypt payload with app's secret
        $encrypter = new Encrypter(
            $application->client_secret,
            config('app.cipher')  // 'AES-256-CBC'
        );

        $encoded = $encrypter->encrypt($payload);

        // 4. Redirect to external app with token
        return redirect()->away(
            $application->redirect_url . '/sso-login?token=' . urlencode($encoded)
        );

    } catch (\Exception $e) {
        return redirect()->back()->with(
            'error',
            'Failed to process SSO login: ' . $e->getMessage()
        );
    }
}

Step-by-Step Explanation:

  1. Load App Configuration

    $application = Client::where('id', $appId)->first();

    Get app settings from database

  2. Create Payload

    $payload = json_encode([...])

    JSON object containing user & app info

  3. Encrypt

    $encrypter = new Encrypter($secret, 'AES-256-CBC');
    $encoded = $encrypter->encrypt($payload);

    AES-256 encryption (military-grade)

  4. Redirect

    redirect()->away($url . '?token=' . $encoded);

    Browser redirects to external app


3. SSO Token Generation

3.1 Token Payload Structure

{
    "app_id": 1,
    "client_id": "abc123def456...",
    "client_secret": "xyz789uvw...",
    "email": "juan.delacruz@company.com",
    "name": "Juan Dela Cruz",
    "roles": ["employee", "team-lead"],
    "user_id": 5,
    "expiry": 1733347200
}

Field Descriptions:

Field Purpose Example
app_id Identify which app this is for 1
client_id App's public identifier 32-char random string
client_secret Encryption key (also app identifier) 32-char random string
email User's email juan@company.com
name User's full name Juan Dela Cruz
roles User's system roles ["employee"]
user_id User's DTR ID 5
expiry Unix timestamp (token expires) 1733347200

3.2 Encryption Process

Algorithm: AES-256-CBC

Plain Text Payload
    ↓
Add padding (PKCS7)
    ↓
Generate random IV (initialization vector)
    ↓
Encrypt with client_secret key
    ↓
Combine: IV + encrypted_data
    ↓
Base64 encode
    ↓
Encrypted Token (safe for URL)

Example:

Before: {"email":"juan@company.com", ...}
After: eyJpdiI6Ij...ZjFyTnJFZHMrb...==

3.3 Token Lifespan

Token Created:  2025-12-04 08:30:00
Expiry Time:    +60 minutes
Token Expires:  2025-12-04 09:30:00

After 60 minutes:

  • ❌ Token is invalid
  • ❌ External app rejects it
  • ✅ User must initiate SSO again

4. Models & Database

4.1 Client Model

File: app/Models/Client.php

class Client extends Model
{
    use HasFactory;

    protected $fillable = [
        'name',
        'client_id',
        'client_secret',
        'redirect_url',
        'is_sso'
    ];

    // Relationship to icon/image
    public function icon()
    {
        return $this->morphOne(Attachment::class, 'attachable');
    }

    // Auto-generate IDs on creation
    public static function boot()
    {
        parent::boot();

        static::creating(function ($client) {
            $client->client_id = Str::random(32);
            $client->client_secret = Str::random(32);
        });
    }
}

Key Features:

  • ✅ Auto-generates random client_id & secret
  • ✅ Relationship with icon attachment
  • ✅ Fillable attributes for mass assignment

4.2 Clients Table Schema

CREATE TABLE clients (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    client_id VARCHAR(255) UNIQUE NOT NULL,
    client_secret VARCHAR(255) NOT NULL,
    redirect_url TEXT NOT NULL,
    is_sso BOOLEAN DEFAULT true,
    created_at TIMESTAMP,
    updated_at TIMESTAMP
);

Column Descriptions:

Column Type Purpose
id BIGINT Primary key
name VARCHAR App name (e.g., "HR System")
client_id VARCHAR Public ID (random 32 chars)
client_secret VARCHAR Encryption key (random 32 chars)
redirect_url TEXT External app URL
is_sso BOOLEAN Enable/disable SSO feature
created_at TIMESTAMP Record created time
updated_at TIMESTAMP Last modified time

4.3 Attachments (Icons)

// Get app icon
$app = Client::with('icon')->first();
echo $app->icon->path;  // /storage/app/icons/hr-system.png

Morphable Relationship:

// In Attachment model
public function attachable()
{
    return $this->morphTo();
}

// In Client model
public function icon()
{
    return $this->morphOne(Attachment::class, 'attachable');
}

5. Security Implementation

5.1 Token Encryption

Laravel Encrypter Class:

use Illuminate\Encryption\Encrypter;

$encrypter = new Encrypter(
    $secret_key,           // client_secret
    'AES-256-CBC'          // cipher algorithm
);

// Encrypt
$encrypted = $encrypter->encrypt($payload);

// Decrypt (done by external app)
$decrypted = $encrypter->decrypt($encrypted);

Security Levels:

✅ Level 1: HTTPS (data in transit)
✅ Level 2: AES-256 encryption (data at rest)
✅ Level 3: Signature validation (prevent tampering)
✅ Level 4: Timestamp validation (prevent replay)

5.2 External App Verification

What the receiving app must do:

// External app: HR System (https://hr.company.com)

// 1. Get encrypted token from URL
$token = request()->input('token');

// 2. Load DTR app config (must know client_secret)
$clientSecret = config('dtr.client_secret');

// 3. Decrypt with same secret
$encrypter = new Encrypter($clientSecret, 'AES-256-CBC');
$payload = $encrypter->decrypt($token);
$data = json_decode($payload, true);

// 4. Validate expiry time
if ($data['expiry'] < time()) {
    abort(401, 'Token expired');
}

// 5. Validate client_id matches
if ($data['client_id'] !== config('dtr.client_id')) {
    abort(401, 'Invalid client');
}

// 6. Create user session
auth()->login(User::findOrCreate($data['email']));

5.3 Shared Secrets

How External App Gets Secret:

  1. Admin Portal: HR system admin logs into DTR
  2. Generate App: Creates new "HR System" client
  3. Receive Credentials:
    • client_id: "abc123..."
    • client_secret: "xyz789..."
  4. Configure HR App: Enter credentials in config
  5. Enable SSO: HR app now accepts DTR tokens

Example HR System Config:

// config/dtr.php
return [
    'client_id' => 'abc123def456...',
    'client_secret' => 'xyz789uvw...',
    'redirect_url' => 'https://hr.company.com/sso-login'
];

5.4 Best Practices

DO:

  • Use HTTPS always
  • Rotate secrets periodically
  • Log SSO attempts
  • Validate token expiry strictly
  • Don't log sensitive data

DON'T:

  • Store secrets in code (use config files)
  • Share secrets via email
  • Use weak algorithms
  • Accept expired tokens
  • Log user passwords/tokens

6. Integration Guide

6.1 Adding New External App

Step 1: Create Client in DTR Admin

# Via admin panel or artisan command
php artisan tinker
> Client::create([
    'name' => 'HR System',
    'redirect_url' => 'https://hr.company.com/sso-login',
    'is_sso' => true
])

Step 2: Get Credentials

> $app = Client::where('name', 'HR System')->first()
> $app->client_id    // Share with HR admin
> $app->client_secret  // Share with HR admin (securely!)

Step 3: Configure External App

HR system admin enters in their config:

'dtr_client_id' => 'abc123...',
'dtr_client_secret' => 'xyz789...',

Step 4: Test SSO

  1. Login to DTR
  2. Navigate to Apps
  3. Click "Login (SSO)" for HR System
  4. Should be logged in to HR system

6.2 Routes & URLs

DTR Routes:

// routes/web.php
Route::get('/apps', [AppController::class, 'apps'])
    ->name('apps.index');

Route::get('/apps/landing/{appId}',
    [AppController::class, 'applicatonLanding'])
    ->name('apps.landing');

URL Examples:

Display apps:
https://dtr.company.com/apps

Initiate SSO for app #1:
https://dtr.company.com/apps/landing/1

After SSO (redirects to):
https://hr.company.com/sso-login?token=eyJ...

6.3 Blade Template Integration

File: resources/views/apps/index.blade.php

Key Parts:

<!-- Fetch apps from controller -->
@foreach ($apps as $app)
    <!-- App Card -->
    <div x-data="{ showModal: false }">
        <a @click.prevent="showModal = true">
            <!-- App icon & name -->
        </a>

        <!-- Modal Dialog -->
        <div x-show="showModal">
            <!-- Show app details -->

            @if ($app->is_sso)
                <!-- SSO button -->
                <a href="{{ route('apps.landing', ['appId' => $app->id]) }}">
                    Login (SSO)
                </a>
            @endif

            <!-- Direct link -->
            <a href="{{ $app->redirect_url }}" target="_blank">
                View Page
            </a>
        </div>
    </div>
@endforeach

Summary Table

Component Technology Purpose
Controller Laravel Handle requests & SSO logic
Model Eloquent Database access
Encryption AES-256-CBC Secure token generation
View Blade + Alpine.js App launcher UI
Routes Laravel Routes URL mapping

Documentation Version: 1.0
Last Updated: December 4, 2025
Status: ✅ Complete