/
home
/
infinitibizsol
/
.trash
/
node_modules.9
/
mongodb
/
lib
/
cmap
/
auth
/
mongodb_oidc
/
File Upload :
llllll
Current File: /home/infinitibizsol/.trash/node_modules.9/mongodb/lib/cmap/auth/mongodb_oidc/callback_workflow.js
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CallbackWorkflow = void 0; const bson_1 = require("bson"); const error_1 = require("../../../error"); const utils_1 = require("../../../utils"); const providers_1 = require("../providers"); const callback_lock_cache_1 = require("./callback_lock_cache"); const token_entry_cache_1 = require("./token_entry_cache"); /** The current version of OIDC implementation. */ const OIDC_VERSION = 0; /** 5 minutes in seconds */ const TIMEOUT_S = 300; /** Properties allowed on results of callbacks. */ const RESULT_PROPERTIES = ['accessToken', 'expiresInSeconds', 'refreshToken']; /** Error message when the callback result is invalid. */ const CALLBACK_RESULT_ERROR = 'User provided OIDC callbacks must return a valid object with an accessToken.'; /** * OIDC implementation of a callback based workflow. * @internal */ class CallbackWorkflow { /** * Instantiate the workflow */ constructor() { this.cache = new token_entry_cache_1.TokenEntryCache(); this.callbackCache = new callback_lock_cache_1.CallbackLockCache(); } /** * Get the document to add for speculative authentication. This also needs * to add a db field from the credentials source. */ async speculativeAuth(credentials) { const document = startCommandDocument(credentials); document.db = credentials.source; return { speculativeAuthenticate: document }; } /** * Execute the OIDC callback workflow. */ async execute(connection, credentials, reauthenticating, response) { // Get the callbacks with locks from the callback lock cache. const { requestCallback, refreshCallback, callbackHash } = this.callbackCache.getEntry(connection, credentials); // Look for an existing entry in the cache. const entry = this.cache.getEntry(connection.address, credentials.username, callbackHash); let result; if (entry) { // Reauthentication cannot use a token from the cache since the server has // stated it is invalid by the request for reauthentication. if (entry.isValid() && !reauthenticating) { // Presence of a valid cache entry means we can skip to the finishing step. result = await this.finishAuthentication(connection, credentials, entry.tokenResult, response?.speculativeAuthenticate?.conversationId); } else { // Presence of an expired cache entry means we must fetch a new one and // then execute the final step. const tokenResult = await this.fetchAccessToken(connection, credentials, entry.serverInfo, reauthenticating, callbackHash, requestCallback, refreshCallback); try { result = await this.finishAuthentication(connection, credentials, tokenResult, reauthenticating ? undefined : response?.speculativeAuthenticate?.conversationId); } catch (error) { // If we are reauthenticating and this errors with reauthentication // required, we need to do the entire process over again and clear // the cache entry. if (reauthenticating && error instanceof error_1.MongoError && error.code === error_1.MONGODB_ERROR_CODES.Reauthenticate) { this.cache.deleteEntry(connection.address, credentials.username, callbackHash); result = await this.execute(connection, credentials, reauthenticating); } else { throw error; } } } } else { // No entry in the cache requires us to do all authentication steps // from start to finish, including getting a fresh token for the cache. const startDocument = await this.startAuthentication(connection, credentials, reauthenticating, response); const conversationId = startDocument.conversationId; const serverResult = bson_1.BSON.deserialize(startDocument.payload.buffer); const tokenResult = await this.fetchAccessToken(connection, credentials, serverResult, reauthenticating, callbackHash, requestCallback, refreshCallback); result = await this.finishAuthentication(connection, credentials, tokenResult, conversationId); } return result; } /** * Starts the callback authentication process. If there is a speculative * authentication document from the initial handshake, then we will use that * value to get the issuer, otherwise we will send the saslStart command. */ async startAuthentication(connection, credentials, reauthenticating, response) { let result; if (!reauthenticating && response?.speculativeAuthenticate) { result = response.speculativeAuthenticate; } else { result = await connection.commandAsync((0, utils_1.ns)(credentials.source), startCommandDocument(credentials), undefined); } return result; } /** * Finishes the callback authentication process. */ async finishAuthentication(connection, credentials, tokenResult, conversationId) { const result = await connection.commandAsync((0, utils_1.ns)(credentials.source), finishCommandDocument(tokenResult.accessToken, conversationId), undefined); return result; } /** * Fetches an access token using either the request or refresh callbacks and * puts it in the cache. */ async fetchAccessToken(connection, credentials, serverInfo, reauthenticating, callbackHash, requestCallback, refreshCallback) { // Get the token from the cache. const entry = this.cache.getEntry(connection.address, credentials.username, callbackHash); let result; const context = { timeoutSeconds: TIMEOUT_S, version: OIDC_VERSION }; // Check if there's a token in the cache. if (entry) { // If the cache entry is valid, return the token result. if (entry.isValid() && !reauthenticating) { return entry.tokenResult; } // If the cache entry is not valid, remove it from the cache and first attempt // to use the refresh callback to get a new token. If no refresh callback // exists, then fallback to the request callback. if (refreshCallback) { context.refreshToken = entry.tokenResult.refreshToken; result = await refreshCallback(serverInfo, context); } else { result = await requestCallback(serverInfo, context); } } else { // With no token in the cache we use the request callback. result = await requestCallback(serverInfo, context); } // Validate that the result returned by the callback is acceptable. If it is not // we must clear the token result from the cache. if (isCallbackResultInvalid(result)) { this.cache.deleteEntry(connection.address, credentials.username, callbackHash); throw new error_1.MongoMissingCredentialsError(CALLBACK_RESULT_ERROR); } // Cleanup the cache. this.cache.deleteExpiredEntries(); // Put the new entry into the cache. this.cache.addEntry(connection.address, credentials.username || '', callbackHash, result, serverInfo); return result; } } exports.CallbackWorkflow = CallbackWorkflow; /** * Generate the finishing command document for authentication. Will be a * saslStart or saslContinue depending on the presence of a conversation id. */ function finishCommandDocument(token, conversationId) { if (conversationId != null && typeof conversationId === 'number') { return { saslContinue: 1, conversationId: conversationId, payload: new bson_1.Binary(bson_1.BSON.serialize({ jwt: token })) }; } // saslContinue requires a conversationId in the command to be valid so in this // case the server allows "step two" to actually be a saslStart with the token // as the jwt since the use of the cached value has no correlating conversating // on the particular connection. return { saslStart: 1, mechanism: providers_1.AuthMechanism.MONGODB_OIDC, payload: new bson_1.Binary(bson_1.BSON.serialize({ jwt: token })) }; } /** * Determines if a result returned from a request or refresh callback * function is invalid. This means the result is nullish, doesn't contain * the accessToken required field, and does not contain extra fields. */ function isCallbackResultInvalid(tokenResult) { if (tokenResult == null || typeof tokenResult !== 'object') return true; if (!('accessToken' in tokenResult)) return true; return !Object.getOwnPropertyNames(tokenResult).every(prop => RESULT_PROPERTIES.includes(prop)); } /** * Generate the saslStart command document. */ function startCommandDocument(credentials) { const payload = {}; if (credentials.username) { payload.n = credentials.username; } return { saslStart: 1, autoAuthorize: 1, mechanism: providers_1.AuthMechanism.MONGODB_OIDC, payload: new bson_1.Binary(bson_1.BSON.serialize(payload)) }; } //# sourceMappingURL=callback_workflow.js.map
Copyright ©2k19 -
Hexid
|
Tex7ure