nextcloud / server

☁️ Nextcloud server, a safe home for all your data
https://nextcloud.com
GNU Affero General Public License v3.0
27.44k stars 4.08k forks source link

Publish avatar in OAuth payload #18268

Closed MarekPikula closed 3 years ago

MarekPikula commented 4 years ago
**Is your feature request related to a problem? Please describe.** I'm using NextCloud as OAuth2 provider for Rocket.Chat. It has ability to receive user avatar during authentication. ![obraz](https://user-images.githubusercontent.com/1504981/70320988-6b862a00-1826-11ea-85c3-6b0cc040848d.png) **Describe the solution you'd like** It would be nice to send avatar in OAuth2 payload on login, so that it's possible for Rocket.Chat to automatically update it. **Describe alternatives you've considered** There is another option in Rocket.Chat for avatar synchronization which is to provide _Avatar External Provider URL_: ![obraz](https://user-images.githubusercontent.com/1504981/70321282-35957580-1827-11ea-8666-480f32e6b7f7.png) I'm not aware of such URL existing for NextCloud. If there is no such function in API I can create a separate issue.
MarekPikula commented 4 years ago

I can see that there is a avatar resource, for example: https://{nextcloud_domain}/avatar/{user_name}/{some_numbers}, but I cannot see documentation about it. Can anyone confirm how it works?

kesselb commented 4 years ago

https://{nextcloud_domain}/avatar/{user_name}/{some_numbers} should work as external provider url. {some_numbers} is the size. If a user set his avatar to private it's only visible to logged in users. But that might be acceptable.

That patch should add the avatar into the payload if you append ?includeAvatar=1 to the url. For example: ocs/v1.php/cloud/user?format=json&includeAvatar=1. Do you know what happens if a attribute is missing? Is it better to send a empty value as avatar or just not set the attribute :confused:

Index: apps/provisioning_api/lib/Controller/UsersController.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- apps/provisioning_api/lib/Controller/UsersController.php    (revision aaff6a024239a172894e1fe1ca2f90242a698e9f)
+++ apps/provisioning_api/lib/Controller/UsersController.php    (date 1583266108068)
@@ -49,6 +49,7 @@
 use OCP\AppFramework\Http\DataResponse;
 use OCP\AppFramework\OCS\OCSException;
 use OCP\AppFramework\OCS\OCSForbiddenException;
+use OCP\IAvatarManager;
 use OCP\IConfig;
 use OCP\IGroup;
 use OCP\IGroupManager;
@@ -91,6 +92,8 @@
     * @param NewUserMailHelper $newUserMailHelper
     * @param FederatedFileSharingFactory $federatedFileSharingFactory
     * @param ISecureRandom $secureRandom
+    * @param RemoteWipe $remoteWipe
+    * @param IAvatarManager $avatarManager
     */
    public function __construct(string $appName,
                                IRequest $request,
@@ -105,14 +108,16 @@
                                NewUserMailHelper $newUserMailHelper,
                                FederatedFileSharingFactory $federatedFileSharingFactory,
                                ISecureRandom $secureRandom,
-                               RemoteWipe $remoteWipe) {
+                               RemoteWipe $remoteWipe,
+                               IAvatarManager $avatarManager) {
        parent::__construct($appName,
                            $request,
                            $userManager,
                            $config,
                            $groupManager,
                            $userSession,
-                           $accountManager);
+                           $accountManager,
+                           $avatarManager);

        $this->appManager = $appManager;
        $this->logger = $logger;
@@ -387,7 +392,7 @@
     * @return DataResponse
     * @throws OCSException
     */
-   public function getUser(string $userId): DataResponse {
+   public function getUser(string $userId ): DataResponse {
        $data = $this->getUserData($userId);
        // getUserData returns empty array if not enough permissions
        if (empty($data)) {
Index: apps/provisioning_api/lib/Controller/AUserData.php
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- apps/provisioning_api/lib/Controller/AUserData.php  (revision aaff6a024239a172894e1fe1ca2f90242a698e9f)
+++ apps/provisioning_api/lib/Controller/AUserData.php  (date 1583266040951)
@@ -31,6 +31,7 @@
 namespace OCA\Provisioning_API\Controller;

 use OC\Accounts\AccountManager;
+use OC\Avatar\AvatarManager;
 use OC\User\Backend;
 use OC\User\NoUserException;
 use OC_Helper;
@@ -38,6 +39,7 @@
 use OCP\AppFramework\OCS\OCSNotFoundException;
 use OCP\AppFramework\OCSController;
 use OCP\Files\NotFoundException;
+use OCP\IAvatarManager;
 use OCP\IConfig;
 use OCP\IGroupManager;
 use OCP\IRequest;
@@ -58,6 +60,8 @@
    protected $userSession;
    /** @var AccountManager */
    protected $accountManager;
+   /** @var AvatarManager */
+   protected $avatarManager;

    /**
     * @param string $appName
@@ -67,6 +71,7 @@
     * @param IGroupManager $groupManager
     * @param IUserSession $userSession
     * @param AccountManager $accountManager
+    * @param IAvatarManager $avatarManager
     */
    public function __construct(string $appName,
                                IRequest $request,
@@ -74,7 +79,8 @@
                                IConfig $config,
                                IGroupManager $groupManager,
                                IUserSession $userSession,
-                               AccountManager $accountManager) {
+                               AccountManager $accountManager,
+                               IAvatarManager $avatarManager) {
        parent::__construct($appName, $request);

        $this->userManager = $userManager;
@@ -82,6 +88,7 @@
        $this->groupManager = $groupManager;
        $this->userSession = $userSession;
        $this->accountManager = $accountManager;
+       $this->avatarManager = $avatarManager;
    }

    /**
@@ -148,6 +155,16 @@
        $data['language'] = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'lang');
        $data['locale'] = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'locale');

+       $includeAvatar = $this->request->getParam('includeAvatar', '0') === '1';
+       if ($includeAvatar) {
+           try {
+               $avatar = $this->avatarManager->getAvatar($targetUserObject->getUID());
+               $data[AccountManager::PROPERTY_AVATAR] = base64_encode($avatar->get(256)->data());
+           } catch (\Exception $e) {
+               // skip avatar on exception
+           }
+       }
+
        $backend = $targetUserObject->getBackend();
        $data['backendCapabilities'] = [
            'setDisplayName' => $backend instanceof ISetDisplayNameBackend || $backend->implementsActions(Backend::SET_DISPLAYNAME),
kesselb commented 4 years ago

Oh. It seems they expect a URL to a avatar. Above patch will include the avatar as base64.

szaimen commented 3 years ago

@kesselb was your patch already included into or could you create a PR with that? Thanks!

ghost commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity and seems to be missing some essential information. It will be closed if no further activity occurs. Thank you for your contributions.