Jake Vanderwerf
2026-05-11 ac444cba221832c012c0435fdc8339fe9f37febb
assets/js/concise/AuthManager.js
@@ -17,8 +17,8 @@
      this.nonces = {};
      this.subscribers = new Set();
      this.storageKey = 'jvb_auth_state';
      this.cacheMetaKey = 'jvb_auth_meta';
      this.storageKey = `${jvbBase.base}auth_state`;
      this.cacheMetaKey = `${jvbBase.base}auth_meta`;
      this.cacheExpiry = 5 * 60 * 1000; // 5 minutes
      this.init();
@@ -29,21 +29,12 @@
    */
   async init() {
      if (this.isAuthenticating) {
         // Wait for existing auth to complete
         return new Promise(resolve => {
            const checkAuth = setInterval(() => {
               if (this.initialized) {
                  clearInterval(checkAuth);
                  resolve();
               }
            }, 50);
         });
         return this.ready();
      }
      this.isAuthenticating = true;
      try {
         // Check if we have cached auth and cookie hasn't changed
         const cached = this.getCachedAuth();
         if (cached) {
            this.setAuthData(cached);
@@ -53,7 +44,6 @@
            return;
         }
         // Fetch fresh auth data
         await this.fetchAuth();
      } catch (error) {
@@ -66,6 +56,54 @@
   }
   /**
    * Refresh nonce if authentication fails
    */
   async refreshNonce(action = 'wp_rest') {
      try {
         await this.fetchAuth();
         return this.getNonce(action);
      } catch (error) {
         console.error('Failed to refresh nonce:', error);
         return null;
      }
   }
   /**
    * Fetch with automatic nonce refresh on auth failure
    * Use this for all authenticated API requests
    */
   async fetch(url, options = {}) {
      const attempt = async (retryCount = 0) => {
         const isFormData = options.body instanceof FormData;
         const headers = {
            ...(!isFormData && { 'Content-Type': 'application/json' }),
            ...options.headers,
            'X-WP-Nonce': this.getNonce()
         };
         const response = await fetch(url, {
            ...options,
            credentials: 'same-origin',
            headers
         });
         if ((response.status === 403 || response.status === 401) && retryCount === 0) {
            const result = await response.clone().json();
            if (result.code === 'rest_cookie_invalid_nonce' || result.message?.includes('Cookie check')) {
               console.log('Nonce invalid, refreshing auth...');
               await this.refresh();
               return attempt(retryCount + 1);
            }
         }
         return response;
      };
      return attempt();
   }
   /**
    * Fetch authentication status from API
    */
   async fetchAuth() {
@@ -104,9 +142,16 @@
    * Set authentication data
    */
   setAuthData(authData) {
      const wasAuthenticated = this.initialized && this.authenticated;
      this.authenticated = authData.authenticated || false;
      this.user = authData.user || false;
      this.nonces = authData.nonces || {};
      // Session expired — was logged in, now isn't
      if (wasAuthenticated && !this.authenticated) {
         window.location.href = `/login?redirect_to=${encodeURIComponent(window.location.href)}`;
      }
   }
   /**