@aashari/mcp-server-aws-sso
Version:
Node.js/TypeScript MCP server for AWS Single Sign-On (SSO). Enables AI systems (LLMs) with tools to initiate SSO login (device auth flow), list accounts/roles, and securely execute AWS CLI commands using temporary credentials. Streamlines AI interaction w
235 lines (234 loc) • 10.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.detectErrorType = detectErrorType;
const logger_util_js_1 = require("./logger.util.js");
const error_types_util_js_1 = require("./error-types.util.js");
/**
* Detect specific error types from raw errors
* @param error The error to analyze
* @param context Context information for better error detection
* @returns Object containing the error code and status code
*/
function detectErrorType(error, context = {}) {
const methodLogger = logger_util_js_1.Logger.forContext('utils/error-detection.util.ts', 'detectErrorType');
methodLogger.debug(`Detecting error type`, { error, context });
const errorMessage = error instanceof Error ? error.message : String(error);
const statusCode = error instanceof Error && 'statusCode' in error
? error.statusCode
: undefined;
// AWS SSO OIDC API Error Detection
// Check for specific OIDC error codes in error or originalError
if (error instanceof Error) {
// Check for OIDC errors directly in the error object
if ('error' in error && typeof error.error === 'string') {
const oidcErrorCode = error.error;
if (oidcErrorCode === 'authorization_pending') {
return {
code: error_types_util_js_1.ErrorCode.AWS_SSO_AUTH_PENDING,
statusCode: 202,
};
}
if (oidcErrorCode === 'access_denied') {
return { code: error_types_util_js_1.ErrorCode.AWS_SSO_AUTH_DENIED, statusCode: 403 };
}
if (oidcErrorCode === 'expired_token' ||
oidcErrorCode === 'invalid_token' ||
oidcErrorCode === 'invalid_grant') {
return {
code: error_types_util_js_1.ErrorCode.AWS_SSO_TOKEN_EXPIRED,
statusCode: 401,
};
}
if (oidcErrorCode === 'slow_down') {
return { code: error_types_util_js_1.ErrorCode.RATE_LIMIT_ERROR, statusCode: 429 };
}
}
// Check error message for auth-related patterns
if (typeof errorMessage === 'string') {
if (errorMessage.includes('expired') &&
(errorMessage.includes('token') ||
errorMessage.includes('credential'))) {
return {
code: error_types_util_js_1.ErrorCode.AWS_SSO_TOKEN_EXPIRED,
statusCode: 401,
};
}
if (errorMessage.includes('authentication') &&
(errorMessage.includes('pending') ||
errorMessage.includes('not complete'))) {
return {
code: error_types_util_js_1.ErrorCode.AWS_SSO_AUTH_PENDING,
statusCode: 202,
};
}
if (errorMessage.includes('authentication') &&
(errorMessage.includes('denied') ||
errorMessage.includes('rejected'))) {
return {
code: error_types_util_js_1.ErrorCode.AWS_SSO_AUTH_DENIED,
statusCode: 403,
};
}
}
// Check for OIDC error codes in originalError
if ('originalError' in error && error.originalError) {
const originalError = error.originalError;
// OIDC-specific errors in originalError
if (typeof originalError === 'object') {
// Check for error code directly in originalError
if (originalError.error &&
typeof originalError.error === 'string') {
const oidcErrorCode = originalError.error;
if (oidcErrorCode === 'authorization_pending') {
return {
code: error_types_util_js_1.ErrorCode.AWS_SSO_AUTH_PENDING,
statusCode: 202,
};
}
if (oidcErrorCode === 'access_denied') {
return {
code: error_types_util_js_1.ErrorCode.AWS_SSO_AUTH_DENIED,
statusCode: 403,
};
}
if (oidcErrorCode === 'expired_token' ||
oidcErrorCode === 'invalid_token' ||
oidcErrorCode === 'invalid_grant') {
return {
code: error_types_util_js_1.ErrorCode.AWS_SSO_TOKEN_EXPIRED,
statusCode: 401,
};
}
if (oidcErrorCode === 'slow_down') {
return {
code: error_types_util_js_1.ErrorCode.RATE_LIMIT_ERROR,
statusCode: 429,
};
}
if (oidcErrorCode === 'invalid_request') {
return {
code: error_types_util_js_1.ErrorCode.VALIDATION_ERROR,
statusCode: 400,
};
}
}
// Check for error_description in originalError for more context
if (originalError.error_description &&
typeof originalError.error_description === 'string') {
const errorDesc = originalError.error_description;
if (errorDesc.includes('expired') ||
errorDesc.includes('invalid token')) {
return {
code: error_types_util_js_1.ErrorCode.AWS_SSO_TOKEN_EXPIRED,
statusCode: 401,
};
}
if (errorDesc.includes('authorization') &&
(errorDesc.includes('pending') ||
errorDesc.includes('not complete'))) {
return {
code: error_types_util_js_1.ErrorCode.AWS_SSO_AUTH_PENDING,
statusCode: 202,
};
}
}
// AWS SDK Error Detection
if (originalError.name &&
typeof originalError.name === 'string') {
const awsSdkErrorName = originalError.name;
const httpStatusCode = originalError.$metadata &&
typeof originalError.$metadata === 'object'
? originalError.$metadata.httpStatusCode
: undefined;
if (awsSdkErrorName === 'UnauthorizedException' ||
awsSdkErrorName.includes('Unauthorized')) {
return {
code: error_types_util_js_1.ErrorCode.AWS_SDK_PERMISSION_DENIED,
statusCode: httpStatusCode || 403,
};
}
if (awsSdkErrorName === 'ResourceNotFoundException' ||
awsSdkErrorName.includes('NotFound')) {
return {
code: error_types_util_js_1.ErrorCode.AWS_SDK_RESOURCE_NOT_FOUND,
statusCode: httpStatusCode || 404,
};
}
if (awsSdkErrorName === 'TooManyRequestsException' ||
awsSdkErrorName.includes('Throttling')) {
return {
code: error_types_util_js_1.ErrorCode.AWS_SDK_THROTTLING,
statusCode: httpStatusCode || 429,
};
}
if (awsSdkErrorName === 'InvalidRequestException' ||
awsSdkErrorName.includes('Invalid')) {
return {
code: error_types_util_js_1.ErrorCode.AWS_SDK_INVALID_REQUEST,
statusCode: httpStatusCode || 400,
};
}
}
}
}
}
// Network error detection
if (errorMessage.includes('network error') ||
errorMessage.includes('fetch failed') ||
errorMessage.includes('ECONNREFUSED') ||
errorMessage.includes('ENOTFOUND') ||
errorMessage.includes('Failed to fetch') ||
errorMessage.includes('Network request failed')) {
return { code: error_types_util_js_1.ErrorCode.NETWORK_ERROR, statusCode: 500 };
}
// Rate limiting detection
if (errorMessage.includes('rate limit') ||
errorMessage.includes('too many requests') ||
statusCode === 429) {
return { code: error_types_util_js_1.ErrorCode.RATE_LIMIT_ERROR, statusCode: 429 };
}
// AWS SSO Auth timeout
if (errorMessage.includes('timed out') && errorMessage.includes('SSO')) {
return { code: error_types_util_js_1.ErrorCode.AWS_SSO_DEVICE_AUTH_TIMEOUT, statusCode: 408 };
}
// Not Found detection
if (errorMessage.includes('not found') ||
errorMessage.includes('does not exist') ||
statusCode === 404) {
return { code: error_types_util_js_1.ErrorCode.NOT_FOUND, statusCode: 404 };
}
// Access Denied detection
if (errorMessage.includes('access') ||
errorMessage.includes('permission') ||
errorMessage.includes('authorize') ||
errorMessage.includes('authentication') ||
errorMessage.includes('token is invalid') ||
errorMessage.includes('credentials') ||
statusCode === 401 ||
statusCode === 403) {
return { code: error_types_util_js_1.ErrorCode.ACCESS_DENIED, statusCode: statusCode || 403 };
}
// Invalid Cursor detection
if ((errorMessage.includes('cursor') ||
errorMessage.includes('startAt') ||
errorMessage.includes('page')) &&
(errorMessage.includes('invalid') || errorMessage.includes('not valid'))) {
return { code: error_types_util_js_1.ErrorCode.INVALID_CURSOR, statusCode: 400 };
}
// Validation Error detection
if (errorMessage.includes('validation') ||
errorMessage.includes('invalid') ||
errorMessage.includes('required') ||
statusCode === 400 ||
statusCode === 422) {
return {
code: error_types_util_js_1.ErrorCode.VALIDATION_ERROR,
statusCode: statusCode || 400,
};
}
// Default to unexpected error
return {
code: error_types_util_js_1.ErrorCode.UNEXPECTED_ERROR,
statusCode: statusCode || 500,
};
}