Overview

The Session Management system provides comprehensive session tracking, multi-device management, and login activity monitoring. It allows users to view active sessions, manage devices, and monitor login attempts for enhanced security.

Key Features

  • Active Session Tracking: View all active sessions across devices
  • Multi-Device Management: Manage sessions on different devices
  • Remote Logout: Logout from specific devices or all other devices
  • Login Activity History: View login attempts and activity logs
  • Session Statistics: Analyze login patterns and device usage
  • Multi-Step Registration: Guided registration with OTP verification
  • Forget Password Flow: Secure password recovery

Active Sessions

Get Active Sessions

Retrieve all active sessions for the authenticated user. Endpoint: GET /api/auth/sessions Alternative: GET /api/auth/sessions/active Headers:
Authorization: Bearer <access_token>
Response: 200 OK
{
  "code": 200,
  "message": "Active sessions retrieved successfully",
  "data": [
    {
      "id": 1,
      "device_name": "Chrome on MacBook Pro",
      "ip_address": "192.168.1.100",
      "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)...",
      "is_current": true,
      "last_activity": "2025-10-13T12:00:00Z",
      "created_at": "2025-10-13T10:00:00Z",
      "expires_at": "2025-10-20T10:00:00Z"
    },
    {
      "id": 2,
      "device_name": "Safari on iPhone",
      "ip_address": "192.168.1.101",
      "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X)...",
      "is_current": false,
      "last_activity": "2025-10-13T11:30:00Z",
      "created_at": "2025-10-12T15:00:00Z",
      "expires_at": "2025-10-19T15:00:00Z"
    }
  ]
}
Example:
async function getActiveSessions() {
  const accessToken = localStorage.getItem('access_token');
  
  const response = await fetch('https://api.rcoinx.com/api/auth/sessions', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json'
    }
  });
  
  const data = await response.json();
  
  if (!response.ok) {
    throw new Error(data.message);
  }
  
  return data.data;
}

// Usage
try {
  const sessions = await getActiveSessions();
  console.log(`You have ${sessions.length} active sessions`);
  sessions.forEach(session => {
    console.log(`${session.device_name} - ${session.ip_address}`);
  });
} catch (error) {
  console.error('Failed to get sessions:', error);
}

Get Session by ID

Retrieve details of a specific session. Endpoint: GET /api/auth/sessions/:id Headers:
Authorization: Bearer <access_token>
Response: 200 OK
{
  "code": 200,
  "message": "Session retrieved successfully",
  "data": {
    "id": 1,
    "device_name": "Chrome on MacBook Pro",
    "ip_address": "192.168.1.100",
    "user_agent": "Mozilla/5.0...",
    "is_current": true,
    "last_activity": "2025-10-13T12:00:00Z",
    "created_at": "2025-10-13T10:00:00Z",
    "expires_at": "2025-10-20T10:00:00Z",
    "location": {
      "city": "San Francisco",
      "country": "United States"
    }
  }
}

Session Logout

Logout from Specific Session

Logout from a specific session (device). Endpoint: POST /api/auth/sessions/logout Headers:
Authorization: Bearer <access_token>
Request:
{
  "session_id": 2
}
Parameters:
  • session_id: Required, ID of the session to terminate
Response: 200 OK
{
  "code": 200,
  "message": "Session terminated successfully",
  "data": {
    "success": true,
    "session_id": 2
  }
}
Example:
async function logoutSession(sessionId) {
  const accessToken = localStorage.getItem('access_token');
  
  const response = await fetch('https://api.rcoinx.com/api/auth/sessions/logout', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ session_id: sessionId })
  });
  
  const data = await response.json();
  
  if (!response.ok) {
    throw new Error(data.message);
  }
  
  return data.data;
}

Logout from All Other Sessions

Terminate all sessions except the current one. Endpoint: POST /api/auth/sessions/logout-others Headers:
Authorization: Bearer <access_token>
Response: 200 OK
{
  "code": 200,
  "message": "All other sessions terminated successfully",
  "data": {
    "success": true,
    "terminated_count": 3
  }
}
Example:
async function logoutOtherSessions() {
  const accessToken = localStorage.getItem('access_token');
  
  const confirmed = confirm(
    'This will log you out from all other devices. Continue?'
  );
  
  if (!confirmed) return;
  
  const response = await fetch(
    'https://api.rcoinx.com/api/auth/sessions/logout-others',
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Content-Type': 'application/json'
      }
    }
  );
  
  const data = await response.json();
  
  if (!response.ok) {
    throw new Error(data.message);
  }
  
  alert(`Successfully logged out from ${data.data.terminated_count} other devices`);
  return data.data;
}

Login Activity

Get Login Activity

Retrieve the user’s login activity history. Endpoint: GET /api/auth/activity Headers:
Authorization: Bearer <access_token>
Query Parameters:
  • limit: Optional, number of records to return (default: 50, max: 100)
  • offset: Optional, pagination offset (default: 0)
  • success_only: Optional, filter successful logins only (boolean)
Response: 200 OK
{
  "code": 200,
  "message": "Login activity retrieved successfully",
  "data": {
    "activities": [
      {
        "id": 1,
        "action": "login",
        "status": "success",
        "ip_address": "192.168.1.100",
        "user_agent": "Mozilla/5.0...",
        "device_name": "Chrome on MacBook Pro",
        "location": {
          "city": "San Francisco",
          "country": "United States"
        },
        "created_at": "2025-10-13T10:00:00Z"
      },
      {
        "id": 2,
        "action": "login",
        "status": "failed",
        "failure_reason": "incorrect_password",
        "ip_address": "192.168.1.105",
        "user_agent": "Mozilla/5.0...",
        "device_name": "Unknown Device",
        "created_at": "2025-10-13T09:45:00Z"
      }
    ],
    "total": 150,
    "limit": 50,
    "offset": 0
  }
}
Example:
async function getLoginActivity(limit = 50, offset = 0, successOnly = false) {
  const accessToken = localStorage.getItem('access_token');
  
  const params = new URLSearchParams({
    limit: limit.toString(),
    offset: offset.toString()
  });
  
  if (successOnly) {
    params.append('success_only', 'true');
  }
  
  const response = await fetch(
    `https://api.rcoinx.com/api/auth/activity?${params}`,
    {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Content-Type': 'application/json'
      }
    }
  );
  
  const data = await response.json();
  
  if (!response.ok) {
    throw new Error(data.message);
  }
  
  return data.data;
}

Get Activity Statistics

Get statistics about login activity. Endpoint: GET /api/auth/activity/stats Headers:
Authorization: Bearer <access_token>
Query Parameters:
  • days: Optional, number of days to include (default: 30)
Response: 200 OK
{
  "code": 200,
  "message": "Activity statistics retrieved successfully",
  "data": {
    "total_logins": 150,
    "successful_logins": 145,
    "failed_logins": 5,
    "unique_devices": 3,
    "unique_ips": 5,
    "last_login": "2025-10-13T10:00:00Z",
    "most_used_device": "Chrome on MacBook Pro",
    "login_by_day": [
      {
        "date": "2025-10-13",
        "count": 5
      },
      {
        "date": "2025-10-12",
        "count": 3
      }
    ]
  }
}
Example:
async function getActivityStats(days = 30) {
  const accessToken = localStorage.getItem('access_token');
  
  const response = await fetch(
    `https://api.rcoinx.com/api/auth/activity/stats?days=${days}`,
    {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Content-Type': 'application/json'
      }
    }
  );
  
  const data = await response.json();
  
  if (!response.ok) {
    throw new Error(data.message);
  }
  
  return data.data;
}

Registration Flow

Multi-step registration with SMS OTP verification.

Step 1: Start Registration

Begin the registration process. Endpoint: POST /api/auth/register/start Request:
{
  "phone": "1234567890",
  "country_code": "1"
}
Response: 200 OK
{
  "code": 200,
  "message": "Registration started. OTP sent to phone.",
  "data": {
    "session_id": "reg_session_abc123",
    "phone": "1234567890",
    "country_code": "1",
    "expires_at": "2025-10-13T12:10:00Z"
  }
}

Step 2: Verify Phone

Verify the phone number with OTP. Endpoint: POST /api/auth/register/verify-phone Request:
{
  "session_id": "reg_session_abc123",
  "otp_code": "123456"
}
Response: 200 OK
{
  "code": 200,
  "message": "Phone verified successfully",
  "data": {
    "session_id": "reg_session_abc123",
    "phone_verified": true,
    "next_step": "user_details"
  }
}

Step 3: Complete User Details

Provide user details (username, password, email). Endpoint: POST /api/auth/register/user-details Request:
{
  "session_id": "reg_session_abc123",
  "username": "johndoe",
  "email": "john@example.com",
  "password": "SecurePass123!",
  "password_confirmation": "SecurePass123!"
}
Response: 200 OK
{
  "code": 200,
  "message": "User details saved",
  "data": {
    "session_id": "reg_session_abc123",
    "ready_to_complete": true
  }
}

Step 4: Complete Registration

Finalize the registration. Endpoint: POST /api/auth/register/complete Request:
{
  "session_id": "reg_session_abc123"
}
Response: 200 OK
{
  "code": 200,
  "message": "Registration completed successfully",
  "data": {
    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "access_token_expires_at": "2025-10-13T12:30:00Z",
    "refresh_token_expires_at": "2025-10-20T12:00:00Z",
    "user": {
      "id": 123,
      "username": "johndoe",
      "email": {
        "email": "john@example.com",
        "verified": false
      },
      "phone": {
        "phone": "1234567890",
        "country_code": "1",
        "verified": true
      }
    }
  }
}

Registration Session Status

Check the status of a registration session. Endpoint: POST /api/auth/register/status Request:
{
  "session_id": "reg_session_abc123"
}
Response: 200 OK
{
  "code": 200,
  "message": "Registration session status",
  "data": {
    "session_id": "reg_session_abc123",
    "current_step": "user_details",
    "phone_verified": true,
    "details_completed": false,
    "expires_at": "2025-10-13T12:10:00Z"
  }
}

Resend OTP

Resend OTP during registration. Endpoint: POST /api/auth/register/resend-otp Request:
{
  "session_id": "reg_session_abc123"
}
Response: 200 OK
{
  "code": 200,
  "message": "OTP sent successfully",
  "data": {
    "session_id": "reg_session_abc123",
    "expires_at": "2025-10-13T12:15:00Z"
  }
}

Forget Password Flow

Secure password recovery with OTP verification.

Step 1: Start Forget Password

Initiate password reset. Endpoint: POST /api/auth/forget-password/start Request:
{
  "phone": "1234567890",
  "country_code": "1"
}
Response: 200 OK
{
  "code": 200,
  "message": "Password reset initiated. OTP sent.",
  "data": {
    "session_id": "pwd_reset_abc123",
    "phone": "1234567890",
    "country_code": "1",
    "expires_at": "2025-10-13T12:10:00Z"
  }
}

Step 2: Verify OTP

Verify the OTP code. Endpoint: POST /api/auth/forget-password/verify-otp Request:
{
  "session_id": "pwd_reset_abc123",
  "otp_code": "123456"
}
Response: 200 OK
{
  "code": 200,
  "message": "OTP verified successfully",
  "data": {
    "session_id": "pwd_reset_abc123",
    "otp_verified": true,
    "can_reset_password": true
  }
}

Step 3: Reset Password

Set the new password. Endpoint: POST /api/auth/forget-password/reset Request:
{
  "session_id": "pwd_reset_abc123",
  "new_password": "NewSecurePass123!",
  "new_password_confirmation": "NewSecurePass123!"
}
Response: 200 OK
{
  "code": 200,
  "message": "Password reset successful",
  "data": {
    "success": true
  }
}

Forget Password Session Status

Check the status of a password reset session. Endpoint: POST /api/auth/forget-password/status Request:
{
  "session_id": "pwd_reset_abc123"
}
Response: 200 OK
{
  "code": 200,
  "message": "Password reset session status",
  "data": {
    "session_id": "pwd_reset_abc123",
    "current_step": "verify_otp",
    "otp_verified": false,
    "expires_at": "2025-10-13T12:10:00Z"
  }
}

Resend Forget Password OTP

Resend OTP for password reset. Endpoint: POST /api/auth/forget-password/resend-otp Request:
{
  "session_id": "pwd_reset_abc123"
}
Response: 200 OK
{
  "code": 200,
  "message": "OTP sent successfully",
  "data": {
    "session_id": "pwd_reset_abc123",
    "expires_at": "2025-10-13T12:15:00Z"
  }
}

Complete Session Management UI Example

import React, { useState, useEffect } from 'react';

function SessionManager() {
  const [sessions, setSessions] = useState([]);
  const [loading, setLoading] = useState(true);
  
  useEffect(() => {
    loadSessions();
  }, []);
  
  const loadSessions = async () => {
    try {
      const data = await getActiveSessions();
      setSessions(data);
    } catch (error) {
      console.error('Failed to load sessions:', error);
    } finally {
      setLoading(false);
    }
  };
  
  const handleLogoutSession = async (sessionId, deviceName) => {
    const confirmed = confirm(`Logout from ${deviceName}?`);
    if (!confirmed) return;
    
    try {
      await logoutSession(sessionId);
      await loadSessions();
      alert('Session terminated successfully');
    } catch (error) {
      alert('Failed to logout: ' + error.message);
    }
  };
  
  const handleLogoutAll = async () => {
    const confirmed = confirm(
      'This will log you out from all other devices. Continue?'
    );
    if (!confirmed) return;
    
    try {
      const result = await logoutOtherSessions();
      await loadSessions();
      alert(`Logged out from ${result.terminated_count} devices`);
    } catch (error) {
      alert('Failed to logout: ' + error.message);
    }
  };
  
  const formatDate = (dateString) => {
    return new Date(dateString).toLocaleString();
  };
  
  if (loading) return <div>Loading sessions...</div>;
  
  return (
    <div className="session-manager">
      <div className="header">
        <h2>Active Sessions ({sessions.length})</h2>
        <button onClick={handleLogoutAll} disabled={sessions.length <= 1}>
          Logout All Other Devices
        </button>
      </div>
      
      <div className="sessions-list">
        {sessions.map(session => (
          <div
            key={session.id}
            className={`session-card ${session.is_current ? 'current' : ''}`}
          >
            <div className="session-info">
              <h3>
                {session.device_name}
                {session.is_current && <span className="badge">Current</span>}
              </h3>
              <p className="ip">{session.ip_address}</p>
              <p className="activity">
                Last active: {formatDate(session.last_activity)}
              </p>
              <p className="created">
                Created: {formatDate(session.created_at)}
              </p>
            </div>
            
            {!session.is_current && (
              <button
                onClick={() => handleLogoutSession(session.id, session.device_name)}
                className="logout-btn"
              >
                Logout
              </button>
            )}
          </div>
        ))}
      </div>
    </div>
  );
}

export default SessionManager;

Best Practices

1. Auto-Refresh Sessions

function useActiveSessions(refreshInterval = 60000) {
  const [sessions, setSessions] = useState([]);
  
  useEffect(() => {
    loadSessions();
    
    const interval = setInterval(() => {
      loadSessions();
    }, refreshInterval);
    
    return () => clearInterval(interval);
  }, []);
  
  const loadSessions = async () => {
    try {
      const data = await getActiveSessions();
      setSessions(data);
    } catch (error) {
      console.error('Failed to refresh sessions:', error);
    }
  };
  
  return sessions;
}

2. Alert on Suspicious Activity

function detectSuspiciousActivity(activity) {
  const suspicious = [];
  
  // Check for failed logins
  const failedLogins = activity.filter(a => a.status === 'failed');
  if (failedLogins.length > 3) {
    suspicious.push('Multiple failed login attempts detected');
  }
  
  // Check for unknown locations
  const knownCountries = ['United States', 'Canada'];
  const unknownLocations = activity.filter(
    a => !knownCountries.includes(a.location?.country)
  );
  if (unknownLocations.length > 0) {
    suspicious.push('Login from unusual location');
  }
  
  return suspicious;
}

3. Session Timeout Warning

function SessionTimeoutWarning({ expiresAt }) {
  const [timeLeft, setTimeLeft] = useState(0);
  
  useEffect(() => {
    const calculateTimeLeft = () => {
      const now = Date.now();
      const expires = new Date(expiresAt).getTime();
      return Math.max(0, expires - now);
    };
    
    setTimeLeft(calculateTimeLeft());
    
    const interval = setInterval(() => {
      const left = calculateTimeLeft();
      setTimeLeft(left);
      
      if (left === 0) {
        alert('Your session has expired. Please login again.');
        window.location.href = '/login';
      }
    }, 1000);
    
    return () => clearInterval(interval);
  }, [expiresAt]);
  
  const minutes = Math.floor(timeLeft / 60000);
  
  if (minutes > 10) return null;
  
  return (
    <div className="timeout-warning">
      Session expires in {minutes} minutes
    </div>
  );
}