Trongate PHP Framework Docs
Introduction
Quick Start
Basic Concepts
Understanding Routing
Intercepting Requests
Module Fundamentals
Database Operations
Templates
Helpers
Form Handling
Form Validation
Working With Files
Image Manipulation
Working With Dates & Times
Language Control
Security
Tips And Best Practices

The Trongate Security Module

The Trongate_security module provides a centralized way to handle authorization across your application using scenarios.

Instead of scattering security checks throughout your codebase, you call one method and let it route to the appropriate handler:

PHP
$this->trongate_security->make_sure_allowed('scenario_name');

This approach keeps your security logic organized, consistent, and easy to maintain.

What Are Scenarios?

A scenario is a named security context that describes what access control rules should apply.

Examples of scenarios:

  • 'admin panel' - Only administrators can access
  • 'members area' - Any logged-in member can access
  • 'read comment' - Anyone can access (public)
  • 'edit comment' - Only comment owner or admin can access
  • 'premium content' - Only premium subscribers can access

Each scenario routes to a specific module that knows how to handle that particular type of access control.

It is for you - the developer - to decide how many scenarios your application is going to have. You also, as the developer, determine what names each scenario should be given.

How It Works

The Trongate_security module uses a switch statement to delegate scenarios to appropriate modules. The default scenario handles admin panel access by checking for a valid token with user level 1:

PHP
<?php
class Trongate_security extends Trongate {
    
    public function __construct(?string $module_name = null) {
        parent::__construct($module_name);
        block_url($this->module_name);
    }

    public function make_sure_allowed(string $scenario = 'admin panel', array $params = []): mixed {
        switch ($scenario) {
            // case 'members area':
            //     $result = $this->members->make_sure_allowed($scenario, $params);
            //     return $result;
                
            default:
                // Default: admin panel access
                // Checks for a valid token for user level 1 (administrators)
                $token = $this->trongate_tokens->attempt_get_valid_token(1);
                
                if ($token === false) {
                    if (ENV === 'dev') {
                        // Dev mode convenience: create a token and redirect to login
                        redirect('login/login');
                    } else {
                        redirect('login/login');
                    }
                }
                
                return $token;
        }
    }
}

The commented-out case shows how to add custom scenarios. Uncomment and modify as needed for your application.

In development mode (ENV === 'dev'), the login module provides convenience features to streamline development. In production, unauthenticated users are always redirected to the login page at login/login.

The Default Scenario

If you do not specify a scenario, it defaults to 'admin panel':

PHP
// These two calls are identical
$this->trongate_security->make_sure_allowed();
$this->trongate_security->make_sure_allowed('admin panel');

Both check for a valid token with user level 1 (administrators) and redirect to login/login if none is found.

Return Values: Flexible by Design

The method is intentionally open-ended. It can return:

  • String - The validated token
  • Boolean - true for public access, false for denied
  • Object - Complete user object with permissions
  • Array - Custom data structure with multiple values
  • Nothing - Can redirect or die instead of returning

The return type depends on what your scenario needs. You decide.

This flexibility means make_sure_allowed() can adapt to any authorization pattern your application requires.

Example: Discussion Forum

Let us build a hypothetical discussion forum accessible by the public, with special privileges for admin users and member users.

The Requirements

  • Read comments - Open to anyone (no authentication)
  • Create comments - Must be a logged-in member
  • Edit/delete comments - Must be the comment owner OR an admin

Trongate_security.php

Add forum scenarios to the switch statement:

PHP
public function make_sure_allowed(string $scenario = 'admin panel', array $params = []): mixed {
    switch ($scenario) {
        case 'read comment':
            // Public access  -  no authentication required
            return true;
            
        case 'create comment':
            // Must be a member (user level 2)
            $token = $this->trongate_tokens->attempt_get_valid_token(2);
            if ($token === false) {
                redirect('login/login');
            }
            return $token;
            
        case 'edit comment':
        case 'delete comment':
            // Delegate to members module for ownership check
            $result = $this->members->make_sure_allowed($scenario, $params);
            return $result;
            
        default:
            // Admin panel access  -  checks for user level 1 token
            $token = $this->trongate_tokens->attempt_get_valid_token(1);
            
            if ($token === false) {
                redirect('login/login');
            }
            
            return $token;
    }
}

Members.php

The members module handles complex ownership checks:

PHP
public function make_sure_allowed(string $scenario = 'members area', array $params = []): mixed {

    block_url('members/make_sure_allowed');

    switch ($scenario) {
        case 'edit comment':
        case 'delete comment':
            $comment_id = $params['comment_id'] ?? null;
            
            if (!is_numeric($comment_id)) {
                http_response_code(400);
                die('Invalid comment ID');
            }
            
            // Get current user
            $user = $this->trongate_tokens->get_user_obj();
            
            if ($user === false) {
                redirect('login/login');
            }
            
            // Fetch comment
            $comment = $this->db->get_where($comment_id, 'comments');
            
            if (!$comment) {
                http_response_code(404);
                die('Comment not found');
            }
            
            // Check ownership
            if ($comment->trongate_user_id === $user->trongate_user_id) {
                return $user->token; // Owner can edit/delete
            }
            
            // Check admin status
            if ($user->user_level === 'admin') {
                return $user->token; // Admin can edit/delete
            }
            
            // Access denied
            http_response_code(403);
            die('You do not have permission to ' . $scenario);
            
        default:
            return false;
    }
}

The make_sure_allowed() method name, as shown above, uses to prevent URL invocation.

For more information about these topics check out:

Forum_comments.php (Controller)

Using the scenarios in your controller:

PHP
<?php
class Forum_comments extends Trongate {

    public function view(int $comment_id): void {
        // Anyone can read
        $this->trongate_security->make_sure_allowed('read comment');
        
        $data['comment'] = $this->db->get_where($comment_id, 'comments');
        $data['view_file'] = 'view_comment';
        $this->templates->public($data);
    }

    public function create(): void {
        // Must be logged in
        $token = $this->trongate_security->make_sure_allowed('create comment');
        
        $data['view_file'] = 'create_comment';
        $this->templates->members_area($data);
    }

    public function edit(int $comment_id): void {
        // Check ownership or admin rights
        $this->trongate_security->make_sure_allowed('edit comment', [
            'comment_id' => $comment_id
        ]);
        
        $data['comment'] = $this->db->get_where($comment_id, 'comments');
        $data['view_file'] = 'edit_comment';
        $this->templates->members_area($data);
    }

    public function delete(int $comment_id): void {
        // Check ownership or admin rights
        $this->trongate_security->make_sure_allowed('delete comment', [
            'comment_id' => $comment_id
        ]);
        
        $this->db->delete($comment_id, 'comments');
        set_flashdata('Comment deleted successfully');
        redirect('forum_comments/index');
    }

}

This example assumes you have public and members_area templates created.

Using $this->login->make_sure_allowed() Directly

In your own controllers, you can also call the login module directly to check authentication without going through the security module:

PHP
// Check if the current user is logged in as an administrator (user level 1)
$token = $this->login->make_sure_allowed();

if ($token === false) {
    redirect('login/login');
}

The login->make_sure_allowed() method checks the token, validates the user level, and returns the token string if valid, or false if not. In development mode, it provides convenience features; in production, it always requires proper authentication.

The $params Array

The optional $params array allows fine-grained control:

PHP
$params = [
    'comment_id' => 42,
    'action' => 'edit',
    'user_role' => 'moderator'
];

$this->trongate_security->make_sure_allowed('moderate forum', $params);

Pass any data your scenario needs to make authorization decisions.

Building Your Own Scenarios

To add custom scenarios:

  1. Open Trongate_security.php
  2. Add a new case to the switch statement
  3. Either handle inline OR delegate to another module
  4. Return appropriate value (token, boolean, object, etc.)

Example: Premium Content

PHP
case 'premium content':
    $user = $this->trongate_tokens->get_user_obj();
    
    if ($user === false) {
        redirect('login/login');
    }
    
    // Check if user has premium subscription
    $sql = 'SELECT * FROM subscriptions WHERE trongate_user_id = ? AND status = ?';
    $subscription = $this->db->query_bind($sql, [$user->trongate_user_id, 'active'], 'object');
    
    if (empty($subscription)) {
        redirect('subscriptions/upgrade');
    }
    
    return $user; // Return full user object with subscription info

Why Scenarios Win

  • Centralized security logic - All authorization in one place
  • Consistent patterns - Same method call everywhere
  • Easy to audit - Review security in one file
  • Flexible delegation - Complex logic lives in appropriate modules
  • Testable - Mock scenarios for unit tests

Common Patterns

Pattern 1: Public Access

PHP
case 'public page':
    return true;

Pattern 2: Simple Member Check

PHP
case 'members area':
    $token = $this->trongate_tokens->attempt_get_valid_token(2);
    if ($token === false) {
        redirect('login/login');
    }
    return $token;

Pattern 3: Delegate to Module

PHP
case 'complex scenario':
    $result = $this->custom_module->make_sure_allowed($scenario, $params);
    return $result;
  • Use descriptive scenario names - 'edit comment' not 'scenario_7'
  • Delegate complex logic - Keep switch statement clean, push details to modules
  • Return consistent types per scenario - Do not mix tokens and booleans for same scenario
  • Document your scenarios - Add comments explaining what each scenario protects
  • Test thoroughly - Especially ownership checks and edge cases

We're continually improving the Trongate documentation. If anything is incorrect, unclear, incomplete, or could be better, we'd genuinely appreciate your input.

Share your thoughts in the Documentation Feedback.

Leave Feedback About This Page