Nexcloud 28 with DUO Security 2FA (Two Factor)

I use Ubuntu 22.04, APACHE, PHP 8.2 and Nexcloud 28

open and download from

then extract zip to your Nextcloud path at folder [nextcloud_path]/apps/twofactor_duo

=====================================================================

open file [nextcloud_path]/apps/twofactor_duo/appinfo/info.xml

just delete this code

<dependencies>
	<php min-version="5.6" max-version="7.1" />
	<nextcloud min-version="13" max-version="13" />
</dependencies>

and replace this <category>auth</category> to

<category>integration</category>
<category>security</category>

=====================================================================

next, open [nextcloud_path]/config/config.php

add this code before );

'twofactor_duo' => [
  'IKEY' => 'xxxx',
  'SKEY' => 'xxxxx',
  'HOST' => 'xxxxx',
  'AKEY' => 'xxxx',
],

note: for AKEY use IKEY value

=====================================================================

open this files [nextcloud_path]/lib/public/Authentication/TwoFactorAuth/IProvider.php

under “interface IProvider” section find all of the public functions and remove the colon and type after the function name
example: change “public function getId(): string;” to “public function getId();”. This needs to be done for all six public functions.

=====================================================================

open [nextcloud_path]/lib/public/Authentication/TwoFactorAuth/IProvidesCustomCSP.php

search for “public function getCSP”. Comment out line and put in “public function getCSP();”

=====================================================================

open [nextcloud_path]/lib/public/Authentication/TwoFactorAuth/IProvidesCustomCSP.php

search for “public function getCSP”. Comment out line and put in “public function getCSP();”

=====================================================================

open [nextcloud_path]/core/Controller/TwoFactorChallengeController.php

search for “return new StandaloneTemplateResponse” and comment out that line, and add this code

$response = new TemplateResponse($this->appName, 'twofactorshowchallenge', $data, 'guest');
if ($provider instanceof IProvidesCustomCSP) {
  $response->setContentSecurityPolicy($provider->getCSP());
}
return $response;

=====================================================================
after this try to enable twofactor_duo app, you can do it directly from your Nextcloud Apps or use occ from cli

cd /nextcloud/path/directory
sudo -u apache php occ app:enable twofactor_duo

=====================================================================
use cli
sudo -u apache php occ integrity:check-core
you will see INVALID_HASH ( Failed integrity check, invalid hash)
just see under detect file with have invalid hash, had expected hash and current hash

open [nextcloud_path]/core/signature.json

find expected hash and then replace with current hash, do it all

=====================================================================
now we must create signature for twofactor_duo
first we must generate key and then crt

sudo openssl genrsa -des3 -out /etc/ssl/twofactor.key 2048
sudo openssl req -x509 -nodes -days 36500 -newkey rsa:2048 -keyout /etc/ssl/twofactor.key -out /etc/ssl/twofactor.crt
sudo -u apache php occ integrity:sign-app --path apps/twofactor_duo --privateKey /etc/ssl/twofactor.key --certificate /etc/ssl/twofactor.crt

=====================================================================
try to logout and login again

Good Luck

My understanding is, 2FA in Nextcloud is either built-in or can be implemented using SAML (enterprise SSO way of doing this).

Up until v.15 you could query external 2FA system directly, e.g. privacyIDEA.

I believe DUO is in the same category…

Unfortunately, this (direct) ability was never revived…

image

Getting a blank duo screen with nothing being sent or logged on duo’s end.

I saw another thread suggesting using a 40 character AKEY. Extending the AKEY to 40 characters gives me an authentication error. I’m currently using the IKEY value as the AKEY value. I tried swapping the SKEY value in there since it’s 40 characters and get the same authentication error. So went back to the IKEY.

Checking the logs all I’m seeing mentioning Duo is this:

{"reqId":"Y6KnLqaPuRWQVn2S5ffe","level":0,"time":"November 06, 2021 14:30:07","remoteAddr":"IPADDRESS","user":"USER","app":"files_sharing","method":"GET","url":"/index.php/login/challenge/duo","message":"/appinfo/app.php is deprecated, use \\OCP\\AppFramework\\Bootstrap\\IBootstrap on the application class instead.","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.40","version":"21.0.1.1"}

{"reqId":"iuCFFpRWTa2At1ku9ig6","level":3,"time":"November 06, 2021 14:32:52","remoteAddr":"IPADDRESS","user":"USERNAME","app":"core","method":"GET","url":"/index.php/login/selectchallenge?redirect_url=/index.php/apps/dashboard/","message":"two-factor auth provider 'duo' failed to load","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.40","version":"21.0.1.1"}

From my understanding the deprecated error is simply a warning for the dev and doesn’t affect functionality.

The other, “failed to load” doesn’t really give me much to go off of as to why or why not.

Log level is set to 0.

Any tips?

Hi @MRobi

First and foremost for AKEY it should be 40 characters long, so copying IKEY doesn’t work.
To generate the AKEY use

dd if=/dev/random count=1 | sha256sum

Copy the output into your config as AKEY

'twofactor_duo' => [
  'IKEY' => 'xxxx',
  'SKEY' => 'xxxx',
  'HOST' => 'api-xxxxxxxx.duosecurity.com,
  'AKEY' => 'xxxx',
],

Thanks, I had figured that one out and got it working in Jan '22.
I used that command to generate the AKEY. But I also had to modify some of the other commands above from sudo -u apache to sudo -u www-data. Then I was getting permission issues on some files which were set to 0600 with an owner of root. So I changed those to 0777 and owner www-data. After that I was able to get it working, but it would complain about the files that I modified.

Ultimately, I ended up using this fork which worked out of the box and only required adding the config info. Was a much simpler process. Unsure if it’s compatible with v28 though, planning that update for this weekend.