@mongodb-js/oidc-plugin
Advanced tools
Comparing version 0.1.6 to 0.2.0
@@ -82,2 +82,8 @@ /// <reference types="node" /> | ||
* | ||
* The default value is `['auth-code']`, i.e. the Device Authorization Grant | ||
* flow is not enabled by default and needs to be enabled explicitly. | ||
* | ||
* Order of the entries is not relevant. The Authorization Code Flow always | ||
* takes precedence over the Device Authorization Grant flow. | ||
* | ||
* This can either be a static list of supported flows or a function which | ||
@@ -84,0 +90,0 @@ * returns such a list. In the latter case, the function will be called |
@@ -23,3 +23,2 @@ import type { MongoDBOIDCLogEventsMap, OIDCCallbackContext, IdPServerInfo, IdPServerResponse, TypedEventEmitter } from './types'; | ||
private updateStateWithTokenSet; | ||
private verifyValidUrl; | ||
static readonly defaultRedirectURI = "http://localhost:27097/redirect"; | ||
@@ -26,0 +25,0 @@ private authorizationCodeFlow; |
@@ -36,3 +36,2 @@ "use strict"; | ||
const api_1 = require("./api"); | ||
const api_2 = require("./api"); | ||
const child_process_1 = require("child_process"); | ||
@@ -199,3 +198,3 @@ // eslint-disable-next-line @typescript-eslint/consistent-type-imports | ||
? await this.options.allowedFlows({ signal }) | ||
: this.options.allowedFlows ?? api_1.ALL_AUTH_FLOW_TYPES); | ||
: this.options.allowedFlows ?? ['auth-code']); | ||
// Remove flows from the set whose prerequisites aren't fulfilled. | ||
@@ -211,2 +210,6 @@ if (this.options.openBrowser === false) | ||
getAuthState(serverMetadata) { | ||
if (!serverMetadata.issuer || typeof serverMetadata.issuer !== 'string') { | ||
throw new types_1.MongoDBOIDCError(`'issuer' is missing`); | ||
} | ||
(0, util_1.validateSecureHTTPUrl)(serverMetadata.issuer, 'issuer'); | ||
if (!serverMetadata.clientId) { | ||
@@ -252,3 +255,8 @@ throw new types_1.MongoDBOIDCError('No clientId passed in server OIDC metadata object'); | ||
} | ||
(0, util_1.validateSecureHTTPUrl)(serverMetadata.issuer, 'issuer'); | ||
const issuer = await openid_client_2.Issuer.discover(serverMetadata.issuer); | ||
(0, util_1.validateSecureHTTPUrl)(issuer.metadata.authorization_endpoint, 'authorization_endpoint'); | ||
(0, util_1.validateSecureHTTPUrl)(issuer.metadata.device_authorization_endpoint, 'device_authorization_endpoint'); | ||
(0, util_1.validateSecureHTTPUrl)(issuer.metadata.token_endpoint, 'token_endpoint'); | ||
(0, util_1.validateSecureHTTPUrl)(issuer.metadata.jwks_uri, 'jwks_uri'); | ||
const client = new issuer.Client({ | ||
@@ -297,2 +305,3 @@ client_id: serverMetadata.clientId, | ||
async notifyDeviceFlow(deviceFlowInformation) { | ||
(0, util_1.validateSecureHTTPUrl)(deviceFlowInformation.verificationUrl, 'verificationUrl'); | ||
if (!this.options.notifyDeviceFlow) { | ||
@@ -370,20 +379,3 @@ // Should never happen. | ||
} | ||
verifyValidUrl(serverOIDCMetadata, key) { | ||
// Verify that `key` refers to a valid URL. This is currently | ||
// *not* an error that we allow to fall back from. | ||
const value = serverOIDCMetadata[key]; | ||
if (!value || typeof value !== 'string') { | ||
throw new types_1.MongoDBOIDCError(`'${key}' is missing`); | ||
} | ||
else { | ||
try { | ||
new URL(value); | ||
} | ||
catch { | ||
throw new types_1.MongoDBOIDCError(`'${key}' is invalid: ${value}}`); | ||
} | ||
} | ||
} | ||
async authorizationCodeFlow(state, signal) { | ||
this.verifyValidUrl(state.serverOIDCMetadata, 'issuer'); | ||
const configuredRedirectURI = this.options.redirectURI ?? MongoDBOIDCPluginImpl.defaultRedirectURI; | ||
@@ -425,2 +417,3 @@ const codeVerifier = openid_client_2.generators.codeVerifier(); | ||
}); | ||
(0, util_1.validateSecureHTTPUrl)(authCodeFlowUrl, 'authCodeFlowUrl'); | ||
const { localUrl, onAccessed: onLocalUrlAccessed } = await server.addRedirect(authCodeFlowUrl); | ||
@@ -449,3 +442,3 @@ signalCheck(); | ||
if (this.options.openBrowserTimeout !== 0) { | ||
setTimeout(reject, this.options.openBrowserTimeout ?? api_2.kDefaultOpenBrowserTimeout, new types_1.MongoDBOIDCError('Opening browser timed out')).unref(); | ||
setTimeout(reject, this.options.openBrowserTimeout ?? api_1.kDefaultOpenBrowserTimeout, new types_1.MongoDBOIDCError('Opening browser timed out')).unref(); | ||
} | ||
@@ -479,3 +472,2 @@ })); | ||
async deviceAuthorizationFlow(state, signal) { | ||
this.verifyValidUrl(state.serverOIDCMetadata, 'issuer'); | ||
const { scope, client } = await this.getOIDCClient(state); | ||
@@ -482,0 +474,0 @@ await (0, util_1.withAbortCheck)(signal, async ({ signalCheck, signalPromise }) => { |
@@ -23,3 +23,4 @@ /// <reference types="node" /> | ||
export declare function normalizeObject<T extends object>(obj: T): T; | ||
export declare function validateSecureHTTPUrl(url: unknown, diagnosticId: string): void; | ||
export {}; | ||
//# sourceMappingURL=util.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.normalizeObject = exports.withLock = exports.timeoutSignal = exports.AbortSignal = exports.AbortController = exports.errorString = exports.withAbortCheck = exports.throwIfAborted = void 0; | ||
exports.validateSecureHTTPUrl = exports.normalizeObject = exports.withLock = exports.timeoutSignal = exports.AbortSignal = exports.AbortController = exports.errorString = exports.withAbortCheck = exports.throwIfAborted = void 0; | ||
class AbortError extends Error { | ||
@@ -76,2 +76,31 @@ constructor() { | ||
exports.normalizeObject = normalizeObject; | ||
// Throws if the url does not refer to an https: endpoint or a local endpoint, or null or undefined. | ||
function validateSecureHTTPUrl(url, diagnosticId) { | ||
try { | ||
if (url == null) | ||
return; | ||
if (typeof url !== 'string') | ||
throw new Error(`Expected string, got ${typeof url} instead`); | ||
const parsed = new URL(url); | ||
if (parsed.protocol === 'https:') | ||
return; | ||
if (parsed.protocol !== 'http:') { | ||
throw new Error(`Unknown protocol '${parsed.protocol}' '${url}'`); | ||
} | ||
if (!/^(\[::1\]|127(\.\d+){3}|localhost)$/.test(parsed.hostname)) { | ||
throw new Error(`Need to specify https: when accessing non-local URL '${url}'`); | ||
} | ||
} | ||
catch (err) { | ||
if (!err || | ||
typeof err !== 'object' || | ||
!('message' in err) || | ||
typeof err.message !== 'string') { | ||
throw err; | ||
} | ||
err.message += ` (validating: ${diagnosticId})`; | ||
throw err; | ||
} | ||
} | ||
exports.validateSecureHTTPUrl = validateSecureHTTPUrl; | ||
//# sourceMappingURL=util.js.map |
@@ -222,2 +222,8 @@ /// <reference types="node" /> | ||
* | ||
* The default value is `['auth-code']`, i.e. the Device Authorization Grant | ||
* flow is not enabled by default and needs to be enabled explicitly. | ||
* | ||
* Order of the entries is not relevant. The Authorization Code Flow always | ||
* takes precedence over the Device Authorization Grant flow. | ||
* | ||
* This can either be a static list of supported flows or a function which | ||
@@ -224,0 +230,0 @@ * returns such a list. In the latter case, the function will be called |
@@ -16,3 +16,3 @@ { | ||
"homepage": "https://github.com/mongodb-js/oidc-plugin", | ||
"version": "0.1.6", | ||
"version": "0.2.0", | ||
"repository": { | ||
@@ -19,0 +19,0 @@ "type": "git", |
@@ -20,2 +20,3 @@ # @mongodb-js/oidc-plugin | ||
}, | ||
// allowedFlows: ['auth-code', 'device-auth'], // if Device Auth Grant flow is required | ||
}; | ||
@@ -22,0 +23,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
159205
2181
36