Using API with 2FA

Hello everyone,

Iā€™m developing a site where users must be able to log to their Nextcloud account. The 2FA is enabled by default by the administrator of the Nextcloud. I donā€™t really understand how I can use the API with the 2fa.

Can someone give me some info?

Thanks a lot!

hi @lelex86 welcome to the forum :handshake:

Please use the search - lot of issues have been discussed already

in general you can generate ā€œapp passwordsā€ and use it with application which canā€™t utilize the regular browser based Login Flow.

Thanks @wwe. I already look at the discussions I could find. I learn a lot of things, but not really what I was looking for.

Is the app password the only way?

Thank you!

Maybe notā€¦ may be this even not a good way for your problem. As long you donā€™t show what you are doing and what is the problem itā€™s hard to find right solition.

Good afternoon,

I have a site like ā€œexemple.comā€, that needs to connect with a Nextcloud server. The users will never connect to the Nextcloud server, only on the site.

Once on the site, the users need to enter their Nextcloud login information. Then, they will have the list of their files, they can download them and upload a new file.

For the moment, I did a PHP function:

function apiRequest($url, $method, $content = '', $user, $password)
    { 
        //API request start
        $curl = curl_init();
        curl_setopt_array($curl, array(
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
            CURLOPT_USERPWD => "$user:$password",
            CURLOPT_CUSTOMREQUEST => $method,
            CURLOPT_POSTFIELDS => $content,
            CURLOPT_HTTPHEADER => array(
                'OCS-APIRequest: true',
            ),
        ));
        $response = curl_exec($curl);
        $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        $return=array('response'=>$response, 'code'=>$httpCode);
        curl_close($curl);
        // API request end
       
        //Results processing
        if ($httpCode >= 200 && $httpCode < 300) {
            return $return;
        } else { // Errors processing
            $file='./logs/system.log';
            if ($response == false || empty($response)) {
                error_log('Curl error : User: '.$user.' Code : ' . curl_errno($curl) . ', Message : ' . curl_error($curl)."\n".PHP_EOL,3,$file);
            } else {
                
                $xml = new SimpleXMLElement($response);
                $xml = simplexml_load_string($response);
                $message = '';

                if ($xml->getName() === 'd:error') {
                    // Case 1 : error structure with DAV
                    $namespaces = $xml->getNamespaces(true);
                    $xml->registerXPathNamespace('s', $namespaces['s']);

                    $messageNode = $xml->xpath('//s:message');
                    if ($messageNode) {
                        $message = (string) $messageNode[0];
                    }
                } elseif ($xml->getName() === 'ocs') {
                    // Case 2 : error structure with OCS => user
                    $message = (string) $xml->meta->message;
                }
                error_log('API Request error : User: '.$user.' Code : ' . $httpCode . ', Message : ' . $message."\n".PHP_EOL,3,$file);
            }
            return 0;
        }
    }

for the URLs I use:

  • /ocs/v1.php/cloud/user with method ā€˜GETā€™ to test if login information are correct
  • /remote.php/dav/files/ā€™ . $user . '/Documents with method ā€˜PROPFINDā€™ to list the files
  • /remote.php/dav/files/ā€™ . $user . '/Documents/<document_name> with respected method: ā€˜PROPFINDā€™ and ā€˜GETā€™
    to download/upload the document

Itā€™s working well without 2faā€¦

Thanks for your help.
Have a nice day.

the intention if 2FA is exactly how it works - additional secret must be provided together with userid and password. you are asking to break 2FA. You application acts ā€œon behalfā€ the user. curl command is nothing else as ā€œanother browserā€ and needs to provide second factor for successful authentication. There are scenarios when legacy clients do not support modern auth (e.g. WebDAV) - this where you can create fake user/password combination and access the system using single factor auth.

BTW: I donā€™t really get the goal of your applicationā€¦ You can limit the user right to files app only and have native interface to up/download filesā€¦ or access the files using WebDAV which is integral part of the system.

BTW: I donā€™t really get the goal of your applicationā€¦ You can limit the user right to files app only and have native interface to up/download filesā€¦ or access the files using WebDAV which is integral part of the system.

Sure, however the final client wants to have his own site and design, he doesnā€™t want his users to have access directly to the Nextcloud (theyā€™re even on separate web hosting). I was asked to just develop the link between the Nextcloud and the site. The decision and user management is not within my control.

I think your client does not really understand what they are asking for.

Accessing 2FA service without 2FA is a nonsense (while spending money on additional development) ā€¦ Additionally from a security point of view - dealing with clear text credentials of a 3rd-party service?!.. never.ever!!! you are in trouble if you do this. no way to winā€¦

If you are serious developer stop here, discuss the requirements with your client and ask for serious and useful order.

You need to redirect your users to log in through the nextcloud login flow (Login Flow ā€” Nextcloud latest Developer Manual latest documentation) instead of entering the credentials on the site directly. There is no getting around registering a session on the Nextcloud side, that gives you credentials to use in your application.

You should not think of the application as an alternative frontend for the Nextcloud, as that means you need to reimplement A LOT of stuff to make it interact with the Nextcloud backend, like the normal frontend does. Instead think of it like a Nextcloud client, like the mobile clients: They are essentially different frontends to the nextcloud functionality, but they do not re-implement the complex nextcloud frontend login logic influenced by many server apps and instead open it in a webview.

Well, thatā€™s the point. I wanted to know if there was any possibility to use the 2fa with the APIā€¦

Thanks any way.

Thank you, @TessyPowder, for your answer, that finally confirm what I already suspect. Now I can work with that and stop looking for a potential alternative;)

Thanks again.

1 Like

Second factor methods are provided by apps and AFAIK they only return the html code to be shown in the frontend when the second factor is entered and a method for the nextcloud server backend to validate it. The implementation is tied to the nextcloud frontend. I am not aware of any clean API, only html endpoints containing <a>s and <form>s that make it work. That is implemented here: server/core/Controller/TwoFactorChallengeController.php at master Ā· nextcloud/server Ā· GitHub

Other than parsing frontend html and using that an ā€œAPIā€, which you probably donā€™t want to do I see no other way than the login flow, but maybe somebody else knows more than me.

1 Like