Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@
Header, with the fields enclosed by brackets [] replaced by your own identifying
information: "Portions copyright [year] [name of copyright owner]".

Copyright 2023 Wren Security
Copyright 2023-2025 Wren Security
-->
<!DOCTYPE ModuleProperties PUBLIC "=//iPlanet//Authentication Module Properties XML Interface 1.0 DTD//EN"
"jar://com/sun/identity/authentication/Auth_Module_Properties.dtd">

<ModuleProperties moduleName="Duo">
<Callbacks length="0" order="1" timeout="3600" header="#WILL NOT BE SHOWN#" />
<Callbacks length="1" order="2" timeout="3600" header="Login" >
<Callbacks length="2" order="2" timeout="3600" header="Login" >
<TextOutputCallback>Please confirm authentication in your Cisco Duo mobile application.</TextOutputCallback>
<PollingWaitCallback waitTime="5000" />
</Callbacks>
</ModuleProperties>
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* information: "Portions copyright [year] [name of copyright owner]".
*
* Portions copyright 2011-2016 ForgeRock AS.
* Portions copyright 2024 Wren Security.
* Portions copyright 2024-2025 Wren Security.
*/

define([
Expand Down Expand Up @@ -118,6 +118,28 @@ define([
return _.some(requirements.callbacks, ["type", "ConfirmationCallback"]);
}

/**
* Decide if the form template needs to be rendered.
* @param {Object} oldReqs The requirements used for the last render
* @param {Object} newReqs The newly received requirements
* @returns {Boolean} `true` when a render is required
*/
function shouldRenderTemplate (oldReqs, newReqs) {
if (!oldReqs || !newReqs || oldReqs.stage !== newReqs.stage) {
return true;
}
if (!oldReqs.callbacks || !newReqs.callbacks || oldReqs.callbacks.length !== newReqs.callbacks.length) {
return true;
}
return _.some(oldReqs, (oldReq, index) => {
const newReq = newReqs[index];
if (oldReq.type === "PollingWaitCallback" && newReq.type === "PollingWaitCallback") {
return false;
}
return !_.isEqual(oldReq, newReq);
});
}

function getFragmentParamString () {
const params = URIUtils.getCurrentFragmentQueryString();
return _.isEmpty(params) ? "" : `&${params}`;
Expand Down Expand Up @@ -333,9 +355,7 @@ define([
const pollingWaitTimeoutMs = _.find(element.output, { name: "waitTime" }).value;

_.delay(() => {
this.pollingInProgress = true;

if (hasPollingCallback(this.reqs)) {
if (this.reqs === reqs) {
EventManager.sendEvent(Constants.EVENT_LOGIN_REQUEST, { suppressSpinner: true });
}
}, pollingWaitTimeoutMs);
Expand Down Expand Up @@ -367,16 +387,16 @@ define([
});
}

const renderTemplate = shouldRenderTemplate(this.reqs, reqs);

this.reqs = reqs;
this.data.reqs = requirements;

const pollingInProgress = this.pollingInProgress && hasPollingCallback(reqs);

// Is there an attempt at autologin happening?
// if yes then don't render the form until it fails one time
if (urlParams.IDToken1 && Configuration.globalData.auth.autoLoginAttempts === 1) {
Configuration.globalData.auth.autoLoginAttempts++;
} else if (!pollingInProgress) {
} else if (renderTemplate) {
// Attempt to load a stage-specific template to render this form. If not found, use the generic one.
template = `templates/openam/authn/${reqs.stage}.html`;
UIUtils.compileTemplate(template, _.extend({}, Configuration.globalData, this.data))
Expand Down