nextcloud and oauth2 integration tutorial

Keywords: PHP Session curl Database

Basic environment

  • Nextcloud 15.0.5
  • oauth2

Install sociallogin

  1. Download in the official app store sociallogin
  2. Extract and copy sociallogin to app directory
  3. Open Nextcloud and enable it in the application

Configure oauth2

  1. Use the administrator account to open Nextcloud to find the sociallogin settings, select Custom OAuth2 and add oauth2 information, as follows
  2. Set to log in with oauth2 only and cancel system login
    Edit / var/www/html/config/config.php to add the following configuration:

    'social_login_auto_redirect' => true

Use Oauth2 to log out of Nextcloud

In use, it is found that after clicking log out, Nextcloud only logs out its own session and does not log out the session of oauth2, so it will fail to log out
Open core/Controller/LoginController.php to find the logout method. Modify the $response value as follows:

$response = new RedirectResponse('http://10.0.4.3/logout?redirect_uri=http://10.0.4.33:8088');

Create groups with user information

  1. After using oauth2 to log in successfully, in order to distinguish from the original Nextcloud users, Nextcloud will create a user whose user name is oauth2 Internal name + login name in the database. This is inconvenient to use. We can modify the following code to ensure that the user name is normal without prefix:
  2. Create groups based on other information in the returned user information
  • sociallogin/lib/Controller/LoginController.php

    private function login($uid, Profile $profile)
    {
        $user = $this->userManager->get($uid);
        if (null === $user) {
            $connectedUid = $this->socialConnect->findUID($uid);
            $user = $this->userManager->get($connectedUid);
        }
        if ($this->userSession->isLoggedIn()) {
            if (!$this->config->getAppValue($this->appName, 'allow_login_connect')) {
                throw new LoginException($this->l->t('Social login connect is disabled'));
            }
            if (null !== $user) {
                throw new LoginException($this->l->t('This account already connected'));
            }
            $currentUid = $this->userSession->getUser()->getUID();
            $this->socialConnect->connectLogin($currentUid, $uid);
            return new RedirectResponse($this->urlGenerator->linkToRoute('settings.PersonalSettings.index', ['section' => 'additional']));
        }
        if (null === $user) {
            if ($this->config->getAppValue($this->appName, 'disable_registration')) {
                throw new LoginException($this->l->t('Auto creating new users is disabled'));
            }
            if (
                $profile->email && $this->config->getAppValue($this->appName, 'prevent_create_email_exists')
                && count($this->userManager->getByEmail($profile->email)) !== 0
            ) {
                throw new LoginException($this->l->t('Email already registered'));
            }
            $password = substr(base64_encode(random_bytes(64)), 0, 30);
            $user = $this->userManager->createUser($uid, $password);
            $user->setDisplayName($profile->displayName ?: $profile->identifier);
            $user->setEMailAddress((string)$profile->email);
    
            $newUserGroup = $this->config->getAppValue($this->appName, 'new_user_group');
            if ($newUserGroup) {
                try {
                    $group = $this->groupManager->get($newUserGroup);
                    $group->addUser($user);
                } catch (\Exception $e) {
                }
            }
    
            if ($profile->photoURL) {
                $curl = new Curl();
                try {
                    $photo = $curl->request($profile->photoURL);
                    $avatar = $this->avatarManager->getAvatar($uid);
                    $avatar->set($photo);
                } catch (\Exception $e) {
                }
            }
            $this->config->setUserValue($uid, $this->appName, 'disable_password_confirmation', 1);
            if ($profile->data['departmentName'] !== null) {
                $existGroup = $this->groupManager->get($profile->data['departmentName']);
                if ($existGroup === null) {
                    $newGroup = $this->groupManager->createGroup($profile->data['departmentName']);
                    $newGroup->addUser($user);
                } else {
                    $existGroup->addUser($user);
                }
            }
        }
    
        $this->userSession->completeLogin($user, ['loginName' => $user->getUID(), 'password' => null]);
        $this->userSession->createSessionToken($this->request, $user->getUID(), $user->getUID());
    
        if ($redirectUrl = $this->session->get('login_redirect_url')) {
            return new RedirectResponse($redirectUrl);
        }
    
        $this->session->set('last-password-confirm', time());
    
        return new RedirectResponse($this->urlGenerator->getAbsoluteURL('/'));
    }
  • sociallogin/lib/Provider/CustomOAuth2.php
public function getUserProfile()
    {
        $profileFields = array_filter(
            array_map('trim', explode(',', $this->config->get('profile_fields'))),
            function ($val) {
                return !empty($val);
            }
        );
        $profileUrl = $this->config->get('endpoints')->get('profile_url');

        if (count($profileFields) > 0) {
            $profileUrl .= (strpos($profileUrl, '?') !== false ? '&' : '?') . 'fields=' . implode(',', $profileFields);
        }
        $response = $this->apiRequest($profileUrl);
        if (!isset($response->identifier) && isset($response->id)) {
            $response->identifier = $response->id;
        }
        if (!isset($response->identifier) && isset($response->data->id)) {
            $response->identifier = $response->data->id;
        }
        if (!isset($response->identifier) && isset($response->user_id)) {
            $response->identifier = $response->user_id;
        }
        $data = new Data\Collection($response);
        if (!$data->exists('identifier')) {
            throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
        }
        $userProfile = new User\Profile();
        foreach ($data->toArray() as $key => $value) {
            if (property_exists($userProfile, $key)) {
                $userProfile->$key = $value;
            }
        }
        if (!empty($userProfile->email)) {
            $userProfile->emailVerified = $userProfile->email;
        }
        $attributes = new Data\Collection($data->get('attributes'));
        $userProfile->data = [
            "organizationName" => $attributes->get('organizationName'),
            "departmentName" => $attributes->get('departmentName'),
        ];
        if ($attributes->get('name') !== null) {
            $userProfile->displayName = $attributes->get('name');
        }
        return $userProfile;
    }

Posted by apaxson on Thu, 05 Dec 2019 21:30:04 -0800