Skip to content

Commit da87441

Browse files
committed
Add option to skip nonce in auth code request
1 parent 32681c4 commit da87441

File tree

3 files changed

+78
-35
lines changed

3 files changed

+78
-35
lines changed

src/api.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,14 @@ export interface MongoDBOIDCPluginOptions {
197197
* broken identity providers.
198198
*/
199199
passIdTokenAsAccessToken?: boolean;
200+
201+
/**
202+
* Skip the nonce parameter in the Authorization Code request. This could
203+
* be used to work with providers that don't support the nonce parameter.
204+
*
205+
* Default is `false`.
206+
*/
207+
skipNonceInAuthCodeRequest?: boolean;
200208
}
201209

202210
/** @public */

src/plugin.spec.ts

Lines changed: 67 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,19 @@ async function delay(ms: number) {
7777
return await new Promise((resolve) => setTimeout(resolve, ms));
7878
}
7979

80+
function testAuthCodeFlow(
81+
fn: (opts: Partial<MongoDBOIDCPluginOptions>) => Mocha.Func
82+
): void {
83+
for (let skipNonceInAuthCodeRequest of [true, false]) {
84+
describe(`with skipNonceInAuthCodeRequest: ${skipNonceInAuthCodeRequest}`, function () {
85+
it(
86+
'can successfully authenticate with auth code flow',
87+
fn({ skipNonceInAuthCodeRequest })
88+
);
89+
});
90+
}
91+
}
92+
8093
describe('OIDC plugin (local OIDC provider)', function () {
8194
this.timeout(90_000);
8295

@@ -138,18 +151,30 @@ describe('OIDC plugin (local OIDC provider)', function () {
138151
plugin = createMongoDBOIDCPlugin(pluginOptions);
139152
});
140153

141-
it('can request tokens through the browser', async function () {
142-
const result = await requestToken(
143-
plugin,
144-
provider.getMongodbOIDCDBInfo()
145-
);
146-
const accessTokenContents = getJWTContents(result.accessToken);
147-
expect(accessTokenContents.sub).to.equal('testuser');
148-
expect(accessTokenContents.client_id).to.equal(
149-
provider.getMongodbOIDCDBInfo().clientId
150-
);
151-
verifySuccessfulAuthCodeFlowLog(await readLog());
152-
});
154+
testAuthCodeFlow(
155+
(opts) =>
156+
async function () {
157+
pluginOptions = {
158+
...pluginOptions,
159+
...opts,
160+
};
161+
plugin = createMongoDBOIDCPlugin(pluginOptions);
162+
163+
const result = await requestToken(
164+
plugin,
165+
provider.getMongodbOIDCDBInfo()
166+
);
167+
const accessTokenContents = getJWTContents(result.accessToken);
168+
expect(accessTokenContents.sub).to.equal('testuser');
169+
expect(accessTokenContents.client_id).to.equal(
170+
provider.getMongodbOIDCDBInfo().clientId
171+
);
172+
173+
const log = await readLog();
174+
console.log(log);
175+
verifySuccessfulAuthCodeFlowLog(log);
176+
}
177+
);
153178

154179
it('will re-use tokens while they are valid if no username was provided', async function () {
155180
const skipAuthAttemptEvent = once(
@@ -1017,18 +1042,22 @@ describe('OIDC plugin (local OIDC provider)', function () {
10171042
};
10181043
});
10191044

1020-
it('can successfully authenticate with Okta using auth code flow', async function () {
1021-
plugin = createMongoDBOIDCPlugin({
1022-
...defaultOpts,
1023-
allowedFlows: ['auth-code'],
1024-
openBrowser: (opts) =>
1025-
oktaBrowserAuthCodeFlow({ ...opts, username, password }),
1026-
});
1027-
const result = await requestToken(plugin, metadata);
1045+
testAuthCodeFlow(
1046+
(opts) =>
1047+
async function () {
1048+
plugin = createMongoDBOIDCPlugin({
1049+
...defaultOpts,
1050+
allowedFlows: ['auth-code'],
1051+
openBrowser: (opts) =>
1052+
oktaBrowserAuthCodeFlow({ ...opts, username, password }),
1053+
...opts,
1054+
});
1055+
const result = await requestToken(plugin, metadata);
10281056

1029-
validateToken(getJWTContents(result.accessToken));
1030-
verifySuccessfulAuthCodeFlowLog(await readLog());
1031-
});
1057+
validateToken(getJWTContents(result.accessToken));
1058+
verifySuccessfulAuthCodeFlowLog(await readLog());
1059+
}
1060+
);
10321061

10331062
it('can successfully authenticate with Okta using device auth flow', async function () {
10341063
plugin = createMongoDBOIDCPlugin({
@@ -1087,18 +1116,22 @@ describe('OIDC plugin (local OIDC provider)', function () {
10871116
};
10881117
});
10891118

1090-
it('can successfully authenticate with Azure using auth code flow', async function () {
1091-
plugin = createMongoDBOIDCPlugin({
1092-
...defaultOpts,
1093-
allowedFlows: ['auth-code'],
1094-
openBrowser: (opts) =>
1095-
azureBrowserAuthCodeFlow({ ...opts, username, password }),
1096-
});
1097-
const result = await requestToken(plugin, metadata);
1119+
testAuthCodeFlow(
1120+
(opts) =>
1121+
async function () {
1122+
plugin = createMongoDBOIDCPlugin({
1123+
...defaultOpts,
1124+
allowedFlows: ['auth-code'],
1125+
openBrowser: (opts) =>
1126+
azureBrowserAuthCodeFlow({ ...opts, username, password }),
1127+
...opts,
1128+
});
1129+
const result = await requestToken(plugin, metadata);
10981130

1099-
validateToken(getJWTContents(result.accessToken));
1100-
verifySuccessfulAuthCodeFlowLog(await readLog());
1101-
});
1131+
validateToken(getJWTContents(result.accessToken));
1132+
verifySuccessfulAuthCodeFlowLog(await readLog());
1133+
}
1134+
);
11021135

11031136
it('can successfully authenticate with Azure using device auth flow', async function () {
11041137
plugin = createMongoDBOIDCPlugin({

src/plugin.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,9 @@ export class MongoDBOIDCPluginImpl implements MongoDBOIDCPlugin {
657657
let client!: BaseClient;
658658
let actualRedirectURI!: string;
659659

660-
const nonce = generators.nonce();
660+
const nonce = this.options.skipNonceInAuthCodeRequest
661+
? undefined
662+
: generators.nonce();
661663

662664
try {
663665
await withAbortCheck(signal, async ({ signalCheck, signalPromise }) => {

0 commit comments

Comments
 (0)