Newer
Older
smart-home-server / webclient / src / api / auth.js
import { storage } from "./storage";

const STORAGE_KEY = "shserv_access_token";
const STORAGE_KEY_EXPIRES = "shserv_expires_at";

let _accessToken = null;
let _expiresAt = null;

/**
 * Load token from storage on cold start.
 * Call once during app startup so getAccessToken() works synchronously.
 */
export async function initAccessToken() {
  try {
    const token = await storage.get(STORAGE_KEY);
    _accessToken = token || null;
    const raw = await storage.get(STORAGE_KEY_EXPIRES);
    _expiresAt = raw ? Number(raw) : null;
  } catch {
    _accessToken = null;
    _expiresAt = null;
  }
}

/**
 * Set the current OAuth access token for Bearer authentication.
 * Persists to Preferences (native) or localStorage (web).
 * @param {string|null} token
 * @param {number|null} expiresInSeconds — optional lifetime for proactive refresh
 */
export function setAccessToken(token, expiresInSeconds = null) {
  _accessToken = token || null;
  if (expiresInSeconds != null && expiresInSeconds > 0) {
    _expiresAt = Date.now() + expiresInSeconds * 1000;
  } else {
    _expiresAt = null;
  }

  if (_accessToken) {
    storage.set(STORAGE_KEY, _accessToken);
    if (_expiresAt) {
      storage.set(STORAGE_KEY_EXPIRES, String(_expiresAt));
    }
  } else {
    storage.remove(STORAGE_KEY);
    storage.remove(STORAGE_KEY_EXPIRES);
  }
}

/**
 * Get the current access token (sync — relies on in-memory cache).
 * Call initAccessToken() during startup to populate the cache.
 * @returns {string|null}
 */
export function getAccessToken() {
  return _accessToken;
}

/**
 * Get the stored token expiration timestamp (ms since epoch).
 * @returns {number|null}
 */
export function getExpiresAt() {
  return _expiresAt;
}

/**
 * Clear the stored access token (memory + persistent storage).
 */
export function clearAccessToken() {
  _accessToken = null;
  _expiresAt = null;
  storage.remove(STORAGE_KEY);
  storage.remove(STORAGE_KEY_EXPIRES);
}