{"id":"8cc7749a05f2a330","repo":"mongodb/node-mongodb-native","slug":"credentials-required-for-gssapi-authentication","errorCode":null,"errorMessage":"Credentials required for GSSAPI authentication","messagePattern":"Credentials required for GSSAPI authentication","errorType":"validation","errorClass":"MongoMissingCredentialsError","httpStatus":null,"severity":"error","filePath":"src/cmap/auth/gssapi.ts","lineNumber":43,"sourceCode":"  SERVICE_NAME?: string;\n  SERVICE_REALM?: string;\n};\n\nasync function externalCommand(\n  connection: Connection,\n  command: ReturnType<typeof saslStart> | ReturnType<typeof saslContinue>\n): Promise<{ payload: string; conversationId: number }> {\n  const response = await connection.command(ns('$external.$cmd'), command);\n  return response as { payload: string; conversationId: number };\n}\n\nlet krb: Kerberos;\n\nexport class GSSAPI extends AuthProvider {\n  override async auth(authContext: AuthContext): Promise<void> {\n    const { connection, credentials } = authContext;\n    if (credentials == null) {\n      throw new MongoMissingCredentialsError('Credentials required for GSSAPI authentication');\n    }\n\n    const { username } = credentials;\n\n    const client = await makeKerberosClient(authContext);\n\n    const payload = await client.step('');\n\n    const saslStartResponse = await externalCommand(connection, saslStart(payload));\n\n    const negotiatedPayload = await negotiate(client, 10, saslStartResponse.payload);\n\n    const saslContinueResponse = await externalCommand(\n      connection,\n      saslContinue(negotiatedPayload, saslStartResponse.conversationId)\n    );\n\n    const finalizePayload = await finalize(client, username, saslContinueResponse.payload);","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/3366c21a6311e02f1be91da982f9b93d3cce99a0/src/cmap/auth/gssapi.ts#L25-L61","documentation":"Thrown by the GSSAPI (Kerberos) auth provider when authContext.credentials is null/undefined at the start of authentication. The driver cannot construct a Kerberos client principal without a username (and optional password). GSSAPI requires at least a username to form the client ticket request.","triggerScenarios":"In GSSAPI.auth() when credentials is null; happens when authMechanism='GSSAPI' is set but no username was resolved from the connection string or credentials object.","commonSituations":"Connection string like 'mongodb://host/?authMechanism=GSSAPI' with no username; credentials object passed to MongoClient missing username; URI-encoded username stripped by mis-parsing; using GSSAPI without supplying a Kerberos principal.","solutions":["Provide the Kerberos principal as the username in the connection string: 'mongodb://user@REALM@host/?authMechanism=GSSAPI'.","Pass username in the credentials option of MongoClient.","URL-encode any special characters in the principal (the '@' separating realm)."],"exampleFix":"// before\nconst c = new MongoClient('mongodb://host/?authMechanism=GSSAPI');\n\n// after\nconst c = new MongoClient('mongodb://appsvc%40REALM@host/?authMechanism=GSSAPI');","handlingStrategy":"validation","validationCode":"function requirePrincipal(uri: string): void {\n  if (/authMechanism=GSSAPI/i.test(uri) && !/\\/\\/[^/?]*%40|@/.test(uri)) {\n    throw new Error('GSSAPI requires a username (principal) in the URI');\n  }\n}","typeGuard":"import { MongoMissingCredentialsError } from 'mongodb';\nfunction isGSSAPICredentialsError(e: unknown): boolean {\n  return e instanceof MongoMissingCredentialsError && /GSSAPI/.test(e.message);\n}","tryCatchPattern":null,"preventionTips":["Always include the Kerberos principal as the username for GSSAPI.","URL-encode the '@' in user@REALM as %40 in the URI."],"tags":["auth","gssapi","kerberos","credentials"],"analyzedSha":"3366c21a6311e02f1be91da982f9b93d3cce99a0","analyzedAt":"2026-08-04T13:40:15.335Z","schemaVersion":2}