How Authentication Is Handled in the Akash Console Application

The Akash Console implements a layered authentication system that combines Auth0 for identity management, encrypted session cookies for state persistence, and a server-side AuthService with CASL-based permissions to secure API endpoints.

The Akash Console serves as the primary deployment interface for the Akash Network, requiring robust security to manage cloud infrastructure and user identities. Understanding how authentication is handled within the Akash Console application reveals a sophisticated architecture that delegates identity verification to Auth0 while maintaining fine-grained control over authorization through custom decorators and execution context management.

Auth0 Integration and Session Initialization

The entry point for authentication resides in apps/deploy-web/src/pages/api/auth/[...auth0].ts, which implements the standard Auth0 Universal Login flow using Next.js API routes.

Login Flow and Scope Configuration

When a user initiates authentication, the handleLogin function redirects to Auth0 with a reduced scope to minimize data exposure:

await handleLogin(req, res, {
  authorizationParams: { 
    scope: "openid profile email offline_access" 
  }
});

The offline_access scope ensures the application receives a refresh token, enabling long-lived sessions without requiring frequent re-authentication.

Callback Handling and Local User Creation

After successful Auth0 verification, handleCallback processes the identity provider's response. The console creates a local user record through services.sessionService.createLocalUser(session), merging application-specific settings into the session object:

const userSettings = await services.sessionService.createLocalUser(session);
session.user = { ...session.user, ...userSettings };

This pattern separates Auth0 identity data from internal user preferences and permissions.

Session Termination

The logout endpoint clears all appSession* cookies and redirects to the home page, ensuring stale tokens are removed from the client browser immediately.

Server-Side Session Validation

Every protected API request invokes services.getSession(req, res) to validate the current authentication state. The validation logic checks two critical conditions:

if (!session) { 
  res.status(401).json({ error: "Not authenticated" }); 
}
if (accessTokenExpiry <= new Date()) { 
  res.status(401).json({ error: "Not authenticated" }); 
}

If either check fails, the API returns a 401 status and triggers a client-side redirect to the login endpoint. This middleware pattern ensures that expired tokens cannot access protected resources even if the session cookie remains present.

AuthService and Route Protection

The core authorization logic resides in apps/api/src/auth/services/auth.service.ts, implemented as a scoped TSyringe service that maintains user context throughout the request lifecycle.

Execution Context and Current User

AuthService stores the authenticated user in an ExecutionContextService keyed by "CURRENT_USER":

set currentUser(user) {
  this.executionContextService.set("CURRENT_USER", user);
}
get currentUser() {
  const user = this.executionContextService.get("CURRENT_USER")!;
  assert(user, 401);
  return user;
}

This approach enables dependency injection of the current user into any service without passing request objects through the entire call stack.

The Protected Decorator

The Protected decorator provides declarative route security. When applied to a method, it resolves AuthService, asserts authentication status, and optionally validates CASL abilities:

export const Protected = (rules?) => (target, propertyKey, descriptor) => {
  const originalMethod = descriptor.value;
  descriptor.value = function (...args) {
    const authService = container.resolve(AuthService);
    assert(authService.isAuthenticated, 401);
    if (rules) rules.forEach(r => authService.throwUnlessCan(r.action, r.subject));
    return originalMethod.apply(this, args);
  };
  return descriptor;
};

CASL Ability Checks

The ability object (powered by CASL) is stored alongside the user in the execution context, enabling fine-grained permission checks throughout the API layer. The throwUnlessCan method integrates CASL with the application's error handling, automatically returning 403 responses for unauthorized actions.

Email Verification Flow

The console handles email verification through a combination of the Auth0 Management API and a custom HTTP SDK.

Backend Implementation

apps/api/src/auth/services/auth0/auth0.service.ts wraps the Auth0 Management Client to trigger verification jobs:

await this.managementClient.jobs.verifyEmail({ user_id: userId });

The AuthProvider registers the ManagementClient as a singleton using M2M (Machine-to-Machine) credentials:

container.register(ManagementClient, {
  useFactory: instancePerContainerCachingFactory(c => {
    const authConfig = c.resolve(AuthConfigService);
    return new ManagementClient({
      domain: authConfig.get("AUTH0_M2M_DOMAIN"),
      clientId: authConfig.get("AUTH0_M2M_CLIENT_ID"),
      clientSecret: authConfig.get("AUTH0_M2M_SECRET")
    });
  })
});

Frontend SDK Usage

The packages/http-sdk/src/auth/auth-http.service.ts provides client-side methods for verification workflows:

export class AuthHttpService extends HttpService {
  async sendVerificationEmail(userId: string) {
    return this.post("/v1/send-verification-email", { data: { userId } });
  }
  async verifyEmail(email: string) {
    return this.extractData(
      await this.post<VerifyEmailResponse>("/v1/verify-email", { 
        data: { email } 
      }, { withCredentials: true })
    );
  }
}

Summary

  • Auth0 Integration: The console delegates identity verification to Auth0 using Next.js API routes in apps/deploy-web/src/pages/api/auth/[...auth0].ts, handling login, callback, and logout flows.
  • Session Management: Encrypted cookies store Auth0 sessions, with services.sessionService.createLocalUser() merging local user settings into the session after successful authentication.
  • API Protection: apps/api/src/auth/services/auth.service.ts provides the AuthService class and Protected decorator, using TSyringe for dependency injection and CASL for fine-grained authorization.
  • Email Verification: The Auth0 Management Client (configured in apps/api/src/core/providers/auth.provider.ts) handles backend verification jobs, while packages/http-sdk/src/auth/auth-http.service.ts exposes these capabilities to the frontend.

Frequently Asked Questions

How does the Akash Console handle session expiration?

The console validates session expiration on every protected API request by checking the accessTokenExpiry field against the current date in services.getSession(req, res). If the token has expired, the API returns a 401 status code, triggering a client-side redirect to the login endpoint to refresh the session.

What permissions system does the Akash Console use for authorization?

The application uses CASL (Code Access Security Library) for attribute-based authorization. The AuthService stores the CASL ability object in the execution context alongside the current user. The Protected decorator can accept rules that specify required actions and subjects, calling authService.throwUnlessCan() to enforce these permissions before executing the decorated method.

How is the Auth0 Management API integrated into the backend?

The AuthProvider in apps/api/src/core/providers/auth.provider.ts registers the Auth0 ManagementClient as a singleton using TSyringe's instancePerContainerCachingFactory. The client is configured with M2M (Machine-to-Machine) credentials (AUTH0_M2M_DOMAIN, AUTH0_M2M_CLIENT_ID, AUTH0_M2M_SECRET) and injected into Auth0Service to perform administrative tasks like sending verification emails.

Can the Akash Console authentication work without Auth0?

Based on the source code analysis, the authentication system is tightly coupled to Auth0 as the identity provider. The handleLogin and handleCallback functions in the Next.js API routes specifically target Auth0 endpoints, and the Auth0Service relies on the Auth0 Management Client for user management tasks. Replacing Auth0 would require refactoring these specific files and the provider configuration in apps/api/src/core/providers/auth.provider.ts.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →