#}

Authentication Guide

Master JWT setup, user login, and protecting routes with role-based access control

Authentication Guide

Overview

GEMVC provides a robust JWT (JSON Web Token) authentication system with built-in support for role-based access control (RBAC). The system uses HS256 signatures and supports multiple token types for different use cases.

Access Token 5 min (short-lived)
Refresh Token 1 hour (medium-lived)
Login Token 7 days (long-lived)
HS256 Signature Secure signing
info: 90% of GEMVC security is AUTOMATIC! JWT verification happens when you call $request->auth() - no manual token parsing needed.

Environment Configuration

Configure JWT settings in your .env file:

.env
# JWT Security
TOKEN_SECRET='your-very-long-random-secret-key-here'
TOKEN_ISSUER='MyCompany'

# Token Expiration (in seconds)
ACCESS_TOKEN_VALIDATION_IN_SECONDS=300      # 5 minutes
REFRESH_TOKEN_VALIDATION_IN_SECONDS=3600    # 1 hour
LOGIN_TOKEN_VALIDATION_IN_SECONDS=604800    # 7 days
Tip: Use a long, random string for TOKEN_SECRET. Never commit it to version control!

Token Types

Creating Tokens (JWTToken Class)

JWTToken.php
use Gemvc\Http\JWTToken;

// Access Token - Short-lived for API calls (5 min default)
$accessToken = (new JWTToken())->createAccessToken($userId);

// Refresh Token - Medium-lived for token renewal (1 hour default)
$refreshToken = (new JWTToken())->createRefreshToken($userId);

// Login Token - Long-lived for remember me (7 days default)
$loginToken = (new JWTToken())->createLoginToken($userId);

// With additional data
$token = (new JWTToken())->createAccessToken($userId, [
    'role' => 'admin,user',
    'role_id' => 1,
    'company_id' => 5
]);

Token Payload Structure

JWT Payload
{
    "token_id": "unique-token-id",
    "user_id": 123,
    "role": "admin,user",
    "role_id": 1,
    "company_id": 5,
    "employee_id": 10,
    "branch_id": 2,
    "exp": 1234567890,
    "iss": "MyCompany",
    "type": "access"
}

Authentication in API Services

Basic Authentication Check

User.php
// In your API service
public function update(): JsonResponse
{
    // Verify JWT token - returns 401 if invalid
    if (!$this->request->auth()) {
        return $this->request->returnResponse();
    }
    
    // User is authenticated, continue...
    return (new UserController($this->request))->update();
}

Role-Based Authorization

Admin.php
// Require specific roles - returns 403 if unauthorized
public function delete(): JsonResponse
{
    // Only 'admin' or 'moderator' roles can access
    if (!$this->request->auth(['admin', 'moderator'])) {
        return $this->request->returnResponse();
    }
    
    // User has required role, continue...
    return (new AdminController($this->request))->delete();
}
Tip: The auth() method checks BOTH authentication (valid token) and authorization (correct role). No separate checks needed!

Password Security

GEMVC uses Argon2i for password hashing - the industry standard for secure password storage:

CryptHelper.php
use Gemvc\Helper\CryptHelper;

// Hash password (Argon2i)
$hashedPassword = CryptHelper::hashPassword($plainPassword);

// Verify password
$isValid = CryptHelper::passwordVerify($plainPassword, $hashedPassword);

if ($isValid) {
    // Password matches!
}

Complete Login Example

Complete Login Example
// app/api/Auth.php
class Auth extends ApiService
{
    public function login(): JsonResponse
    {
        // Validate input
        if (!$this->request->definePostSchema([
            'email' => 'email',
            'password' => 'string'
        ])) {
            return $this->request->returnResponse();
        }
        
        return (new AuthController($this->request))->login();
    }
}

// app/controller/AuthController.php
class AuthController extends Controller
{
    public function login(): JsonResponse
    {
        $email = $this->request->post['email'];
        $password = $this->request->post['password'];
        
        // Find user
        $user = (new UserModel())->selectByEmail($email);
        if (!$user) {
            return Response::unauthorized('Invalid credentials');
        }
        
        // Verify password
        if (!CryptHelper::passwordVerify($password, $user->password)) {
            return Response::unauthorized('Invalid credentials');
        }
        
        // Generate tokens
        $jwt = new JWTToken();
        $accessToken = $jwt->createAccessToken($user->id, [
            'role' => $user->role
        ]);
        $refreshToken = $jwt->createRefreshToken($user->id);
        
        return Response::success([
            'access_token' => $accessToken,
            'refresh_token' => $refreshToken,
            'user' => $user
        ], 1, 'Login successful');
    }
}

Security Features

  • HS256 Signature - Secure HMAC-SHA256 token signing
  • Expiration Validation - Automatic token expiry checking
  • User ID Validation - Ensures user_id > 0 in tokens
  • Multi-Role Support - Comma-separated roles (admin,user)
  • Token Renewal - Built-in renew() method for extending tokens
  • Argon2i Passwords - Memory-hard hashing algorithm

Next Steps