# Getting Passbolt Functional with Duo Federal for MFA

**URL:** <https://community.passbolt.com/t/getting-passbolt-functional-with-duo-federal-for-mfa/14786>\
**Category:** Community Feedback\
**Created:** [September 24, 2026, 9:57pm UTC](https://community.passbolt.com/t/getting-passbolt-functional-with-duo-federal-for-mfa/14786 "2026-09-24T21:57:49Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![seth.g](https://avatars.discourse-cdn.com/v4/letter/s/bc8723/32.png) [@seth.g](https://community.passbolt.com/u/seth.g)\
**Post date:** [September 24, 2026, 9:57pm UTC](https://community.passbolt.com/t/getting-passbolt-functional-with-duo-federal-for-mfa/14786/1 "2026-09-24T21:57:49Z")

</div>

Hey All,

I leverage Duo Federal for MFA and wanted it integrated into Passbolt. I saw that the api was set to only allow duosecurity, yet I’m restricted to duofederal. Here’s what I did to get it fully functional (specific items were removed for obvious reasons).

I’m using a Rocky 9 VM and running Passbolt directly.

Modified Passbolt’s Duo API hostname validation

File:

/usr/share/php/passbolt/plugins/PassboltCe/MultiFactorAuthentication/src/Service/MfaOrgSettings/MfaOrgSettingsDuoService.php

Code:

`if (!Validation::custom($hostname, '/^api-[a-fA-F0-9]{8,16}\.duosecurity\.com$/')) {`

Made it:

`if (!Validation::custom($hostname, '/^api-[a-fA-F0-9]{8,16}\.(duosecurity\.com|duofederal\.com)$/')) {`

* * *

### Content Security Policy Change

File:

/usr/share/php/passbolt/src/Middleware/ContentSecurityPolicyMiddleware.php

Code:

`"form-action 'self' https://*.duosecurity.com",`

Rather than modifying the Passbolt source middleware, I overrode the CSP in:

File:

/etc/passbolt/passbolt.php

Added:

`'security' => [`  
`'csp' => "default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; connect-src 'self'; base-uri 'self'; frame-src 'self'; frame-ancestors 'none'; form-action 'self' https://*.duosecurity.com https://*.duofederal.com",`  
`],`

##### Original:

return [  
‘App’ =\> [  
// A base URL to use for absolute links.  
// The url where the passbolt instance will be reachable to your end users.  
// This information is need to render images in emails for example  
‘fullBaseUrl’ =\> ‘https://.com’  
],

// Database configuration.  
‘Datasources’ =\> [  
‘default’ =\> [  
‘driver’ =\> ‘Cake\Database\Driver\Mysql’,  
‘host’ =\> ‘localhost’,  
‘port’ =\> ‘’,  
‘username’ =\> ‘root’,  
‘password’ =\> ‘’,  
‘database’ =\> ‘’,  
],  
],

‘passbolt’ =\> [  
// GPG Configuration.  
// The keyring must be owned and accessible by the webserver user.  
// Example: www-data user on Debian  
‘gpg’ =\> [  
// Main server key.  
‘serverKey’ =\> [  
// Server private key fingerprint.  
‘fingerprint’ =\> ‘’,  
‘public’ =\> CONFIG . DS . ‘gpg’ . DS . ‘serverkey.asc’,  
‘private’ =\> CONFIG . DS . ‘gpg’ . DS . ‘serverkey\_private.asc’,  
],  
],  
‘ssl’ =\> [  
‘force’ =\> true,  
]  
],  
];

##### New:

return [  
‘App’ =\> [  
// A base URL to use for absolute links.  
// The url where the passbolt instance will be reachable to your end users.  
// This information is need to render images in emails for example  
‘fullBaseUrl’ =\> ‘https://.com’,  
],

// Database configuration.  
‘Datasources’ =\> [  
‘default’ =\> [  
‘driver’ =\> ‘Cake\Database\Driver\Mysql’,  
‘host’ =\> ‘localhost’,  
‘port’ =\> ‘’,  
‘username’ =\> ‘root’,  
‘password’ =\> ‘’,  
‘database’ =\> ‘’,  
],  
],

‘passbolt’ =\> [  
// GPG Configuration.  
// The keyring must be owned and accessible by the webserver user.  
// Example: www-data user on Debian  
‘gpg’ =\> [  
// Main server key.  
‘serverKey’ =\> [  
// Server private key fingerprint.  
‘fingerprint’ =\> ‘’,  
‘public’ =\> CONFIG . DS . ‘gpg’ . DS . ‘serverkey.asc’,  
‘private’ =\> CONFIG . DS . ‘gpg’ . DS . ‘serverkey\_private.asc’,  
],  
],  
‘ssl’ =\> [  
‘force’ =\> true,  
],  
‘security’ =\> [  
‘csp’ =\> “default-src ‘none’; script-src ‘self’; style-src ‘self’; img-src ‘self’; font-src ‘self’; connect-src ‘self’; base-uri ‘self’; frame-src ‘self’; frame-ancestors ‘none’; form-action ‘self’ https://_.duosecurity.com https://_.duofederal.com”,  
],  
],  
];

This was found by inspecting the network traffic and seeing this in the console:  
Sending form data to ‘https://us–…/mfa/verify/duo/prompt’  
violates the following Content Security Policy directive:  
“form-action ‘self’ https://\*.duosecurity.com”.

* * *

### Set Environmental Variables for Duo Config

Modified the php-fpm www pool config file (running nginx) to include the needed environmental variables.

file:  
/etc/php-fpm.d/www.conf

Code:

under line 24 - 24 group = nginx

add the below:

env[PASSBOLT\_PLUGINS\_MFA\_PROVIDERS\_DUO] = true  
env[PASSBOLT\_PLUGINS\_MFA\_DUO\_CLIENT\_ID] =  
env[PASSBOLT\_PLUGINS\_MFA\_DUO\_CLIENT\_SECRET] =  
env[PASSBOLT\_PLUGINS\_MFA\_DUO\_API\_HOSTNAME] =
