UNPKG

@datalayer/core

Version:

[![Datalayer](https://assets.datalayer.tech/datalayer-25.svg)](https://datalayer.io)

128 lines (127 loc) 4.96 kB
/* * Copyright (c) 2023-2025 Datalayer, Inc. * Distributed under the terms of the Modified BSD License. */ /** * Authentication API functions for the Datalayer platform. * * Provides functions for user login, logout, and authentication management. * * @module api/iam/authentication */ import { requestDatalayerAPI } from '../DatalayerApi'; import { API_BASE_PATHS, DEFAULT_SERVICE_URLS } from '../constants'; import { validateToken } from '../utils/validation'; /** * Authenticate a user with credentials or token * * @param data - Login credentials (either handle+password or token) * @param baseUrl - Base URL for the API (defaults to production IAM URL) * @returns Login response with tokens * @throws {Error} If both credential and token authentication are provided * @throws {Error} If neither authentication method is provided * @throws {Error} If handle is provided without password or vice versa * @throws {Error} If server returns unexpected status code (expects 201 for success, 401 for failure) * * @remarks * Expected status codes: * - 201: Login succeeded * - 401: Login failed (invalid credentials) */ export const login = async (data, baseUrl = DEFAULT_SERVICE_URLS.IAM) => { // Validate that we have either handle+password OR token, but not both const hasCredentials = Boolean(data.handle || data.password); const hasToken = Boolean(data.token); if (hasCredentials && hasToken) { throw new Error('Cannot provide both credentials (handle/password) and token. Use either handle+password or token.'); } if (!hasCredentials && !hasToken) { throw new Error('Must provide either credentials (handle+password) or token for authentication.'); } // If using credentials, ensure both handle and password are provided if (hasCredentials) { if (!data.handle || !data.password) { throw new Error('Both handle and password are required for credential-based authentication.'); } } try { const response = await requestDatalayerAPI({ url: `${baseUrl}${API_BASE_PATHS.IAM}/login`, method: 'POST', body: data, }); // Note: requestDatalayerAPI already handles successful responses (2xx status codes) // If we get here, the login was successful return response; } catch (error) { // Check if it's a response error with status code information if (error.response) { const status = error.response.status; // Expected error: 401 for invalid credentials if (status === 401) { throw new Error(`Login failed: Invalid credentials (${status})`); } // Unexpected status codes throw new Error(`Login failed: Unexpected status code ${status} - ${error.message}`); } // Re-throw other errors (network errors, etc.) throw error; } }; /** * Log out the current user * @param token - Authentication token * @param baseUrl - Base URL for the API (defaults to production IAM URL) * @returns Void response */ export const logout = async (token, baseUrl = DEFAULT_SERVICE_URLS.IAM) => { validateToken(token); return requestDatalayerAPI({ url: `${baseUrl}${API_BASE_PATHS.IAM}/logout`, method: 'GET', token, }); }; /** * Check authentication status * * @param token - Authentication token (required) * @param baseUrl - Base URL for the API (defaults to production IAM URL) * @returns Promise that resolves if authenticated (200), rejects if unauthorized (401) * @throws {Error} If authentication token is missing or invalid * * @remarks * This endpoint checks authentication status, useful for reverse proxy validation. * * Expected status codes: * - 200: Authenticated successfully * - 401: Unauthorized - invalid or missing credentials */ export const checkAuth = async (token, baseUrl = DEFAULT_SERVICE_URLS.IAM) => { validateToken(token); try { const response = await requestDatalayerAPI({ url: `${baseUrl}${API_BASE_PATHS.IAM}/auth`, method: 'GET', token, }); // Note: requestDatalayerAPI already handles successful responses (2xx status codes) // If we get here, authentication was successful (200) return response; } catch (error) { // Check if it's a response error with status code information if (error.response) { const status = error.response.status; // Expected errors if (status === 401) { throw new Error(`Authentication check failed: Unauthorized (${status})`); } // Unexpected status codes throw new Error(`Authentication check failed: Unexpected status code ${status} - ${error.message}`); } // Re-throw other errors (network errors, etc.) throw error; } };