Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | 400x 400x 400x 400x 400x | import { MONGODB_ERROR_CODES, MongoError, MongoOIDCError } from '../../../error'; import { Timeout, TimeoutError } from '../../../timeout'; import { type Connection } from '../../connection'; import { type MongoCredentials } from '../mongo_credentials'; import { OIDC_VERSION, type OIDCCallbackFunction, type OIDCCallbackParams, type OIDCResponse } from '../mongodb_oidc'; import { AUTOMATED_TIMEOUT_MS, CallbackWorkflow } from './callback_workflow'; import { type TokenCache } from './token_cache'; /** * Class implementing behaviour for the non human callback workflow. * @internal */ export class AutomatedCallbackWorkflow extends CallbackWorkflow { /** * Instantiate the human callback workflow. */ constructor(cache: TokenCache, callback: OIDCCallbackFunction) { super(cache, callback); } /** * Execute the OIDC callback workflow. */ async execute(connection: Connection, credentials: MongoCredentials): Promise<void> { // If there is a cached access token, try to authenticate with it. If // authentication fails with an Authentication error (18), // invalidate the access token, fetch a new access token, and try // to authenticate again. // If the server fails for any other reason, do not clear the cache. if (this.cache.hasAccessToken) { const token = this.cache.getAccessToken(); try { return await this.finishAuthentication(connection, credentials, token); } catch (error) { if ( error instanceof MongoError && error.code === MONGODB_ERROR_CODES.AuthenticationFailed ) { this.cache.removeAccessToken(); return await this.execute(connection, credentials); } else { throw error; } } } const response = await this.fetchAccessToken(credentials); this.cache.put(response); connection.accessToken = response.accessToken; await this.finishAuthentication(connection, credentials, response.accessToken); } /** * Fetches the access token using the callback. */ protected async fetchAccessToken(credentials: MongoCredentials): Promise<OIDCResponse> { const controller = new AbortController(); const params: OIDCCallbackParams = { timeoutContext: controller.signal, version: OIDC_VERSION }; if (credentials.username) { params.username = credentials.username; } const timeout = Timeout.expires(AUTOMATED_TIMEOUT_MS); try { return await Promise.race([this.executeAndValidateCallback(params), timeout]); } catch (error) { if (TimeoutError.is(error)) { controller.abort(); throw new MongoOIDCError(`OIDC callback timed out after ${AUTOMATED_TIMEOUT_MS}ms.`); } throw error; } finally { timeout.clear(); } } } |