zorn-v / nextcloud-social-login

GNU Affero General Public License v3.0
198 stars 137 forks source link

Read Discord Groups #390

Closed kousu closed 7 months ago

kousu commented 1 year ago

This plugin is really useful! Really got my team onboard with using NextCloud, fast.

It doesn't seem to be able to read Discord Roles though. This seems to be the code that does that:

https://github.com/zorn-v/nextcloud-social-login/blob/3c69bf58e5183f828ddf3ccd2abec513db1af604/3rdparty/hybridauth/hybridauth/src/Provider/Discord.php#L65-L83

Is there interest in mapping Roles to NextCloud Groups?

pktiuk commented 1 year ago

I would be interested in this feature for my organization, but I am aware that doing it properly could be a bit complicated.

Such functionality would need some kind of mapping configuration (which Discord role should be mapped to which NC group)

kousu commented 1 year ago

Some notes towards a patch!

The existing call to

https://github.com/zorn-v/nextcloud-social-login/blob/3c69bf58e5183f828ddf3ccd2abec513db1af604/3rdparty/hybridauth/hybridauth/src/Provider/Discord.php#L65

reads the user object, which is global across Discord (API docs!), but roles are attached to servers (aka guilds) (API docs!). Which means a couple of things:

  1. This feature is only going to make sense if you use "Allow login only for specified guilds" and then it like, loops over those and reads them.

    I'm not sure how the guild ID makes it from the settings page

    Screert

    over into the plugin so I don't know how I could check this; it doesn't seem to be used in hybridauth/src/Provider/Discord.php, that's for sure.

  2. Granting permission is tricky. So far I've only gotten 401 Unauthorizeds.

    https://stackoverflow.com/questions/63234909/get-roles-of-current-user-in-discord-server#63235124 and https://stackoverflow.com/questions/69518877/discord-oauth2-getting-user-roles-from-exact-guild explain what I'm missing at a theoretical level, but left out the details of what you actually need to click in https://discord.com/developers/applications to make this work.

    I'm pretty unclear how to set this up. The default plugin setup doesn't require creating a bot user -- because it only has to read the global Discord /user/@me API -- but reading guild-specific data is going to require a bot, and that the bot is a member of the guild, and then that it either has the guilds.members.read OAuth2 scope, or maybe the GUILD_MEMBERS intent, whatever that is.

Here's some code that should do the trick, if I could figure out how to read the guild ID and could get the permissions to work

        # https://discord.com/developers/docs/resources/guild#get-guild-member
        $guild_id = "??????????";
        $guild_response = $this->apiRequest('guilds/' . $guild_id . '/members/' . $data->get('id') );
        $guild_data = new Data\Collection($guild_response);
        if (!$guild_data->exists('roles')) {
            throw new UnexpectedApiResponseException('Provider API returned an unexpected response.');
        }
        $userProfile->data['groups'] = $guild_data->get('roles');
kousu commented 1 year ago

Such functionality would need some kind of mapping configuration (which Discord role should be mapped to which NC group)

My half-finished patch above doesn't do any mapping. Looking ahead, the Custom OpenID Connect and Custom Discourse providers have this mapping button in the UI:

Screenshot 2023-02-14 at 02-08-41 Social login

which seem to be implemented like this:

https://github.com/zorn-v/nextcloud-social-login/blob/8859c1434c3c895861dac69267712b3f70d5a34b/lib/Provider/CustomOpenIDConnect.php#L47-L52

https://github.com/zorn-v/nextcloud-social-login/blob/8859c1434c3c895861dac69267712b3f70d5a34b/lib/Provider/CustomDiscourse.php#L208-L213

I think for my first draft I would be happy if I could just get the groups read in at all!

kousu commented 1 year ago

I have a patch in ^. Do you think you're brave enough to try it out, @pktiuk ?

pktiuk commented 1 year ago

IDK how to run this kind of patch. (I am not an advanced NC user).

kousu commented 1 year ago

I'm not 100% sure how to collaborate with this sort of thing. I am guessing my way through as well.

What I know is that the contents of this repo seem to have been installed directly (including even non-functional files like CHANGELOG.md) to my nextcloud's apps/sociallogin/ folder:

www-data@org:~/nextcloud/apps/sociallogin$ pwd
/var/www/nextcloud/apps/sociallogin
www-data@org:~/nextcloud/apps/sociallogin$ ls -la
total 108
drwxr-xr-x 10 www-data www-data  4096 Feb 14 01:03 .
drwxr-xr-x 65 www-data www-data  4096 Feb  4 05:23 ..
drwxr-xr-x  5 www-data www-data  4096 Jan 23 23:49 3rdparty
-rw-r--r--  1 www-data www-data 21905 Jan 23 23:49 CHANGELOG.md
-rw-r--r--  1 www-data www-data 34520 Jan 23 23:49 COPYING
-rw-r--r--  1 www-data www-data  5211 Jan 23 23:49 README.md
drwxr-xr-x  2 www-data www-data  4096 Jan 23 23:49 appinfo
drwxr-xr-x  2 www-data www-data  4096 Jan 23 23:49 css
drwxr-xr-x  3 www-data www-data  4096 Jan 23 23:49 img
drwxr-xr-x  2 www-data www-data  4096 Jan 23 23:49 js
drwxr-xr-x  2 www-data www-data  4096 Jan 23 23:49 l10n
drwxr-xr-x 10 www-data www-data  4096 Jan 23 23:49 lib
drwxr-xr-x  2 www-data www-data  4096 Jan 23 23:49 templates

So in theory you should be able to replace it just by cloning this repo into the right place:

cd path/to/your/nextcloud/
cd apps
mv sociallogin sociallogin.disabled
# install my patch
git clone -b discord-roles https://github.com/kousu/nextcloud-social-login.git sociallogin  
cd ..
# nextcloud detects the change and forces this to run to recreate any needed database tables
php ./occ upgrade

and to downgrade again it looks like this works:

cd apps
mv sociallogin sociallogin.kousu
mv sociallogin.disabled sociallogin
cd ..
php ./occ upgrade

I would really appreciate some feedback on this if you are willing to help. The more feedback the faster it's going to be working and the sooner @zorn-v will see that there's both a need and a solution.

pktiuk commented 1 year ago

I will try to launch it tomorrow.

pktiuk commented 1 year ago

I got Error:
obraz

[index] Error: Exception: Undefined constant "OCA\SocialLogin\Service\allowedGuilds" in file '/var/www/html/custom_apps/sociallogin/lib/Service/ProviderService.php' line 419 at <<closure>>

0. /var/www/html/lib/private/AppFramework/App.php line 172
   OC\AppFramework\Http\Dispatcher->dispatch(OCA\SocialLogin\ ... {}, "oauth")
1. /var/www/html/lib/private/Route/Router.php line 298
   OC\AppFramework\App::main("OCA\\SocialLogi ... r", "oauth", OC\AppFramework\ ... {}, ["discord","sociallogin.login.oauth"])
2. /var/www/html/lib/base.php line 1047
   OC\Route\Router->match("/apps/sociallogin/oauth/discord")
3. /var/www/html/index.php line 36
   OC::handleRequest()

GET /apps/sociallogin/oauth/discord?code=pDdWS6wcbjpOOFV0JQDXG30jv5V7qm&state=HA-UOV31RMWBCTXL8YJQIFA2KH74EZ6ND90PG5S
from 37.225.92.137 at 2023-02-18T19:45:32+00:00
kousu commented 1 year ago

Thank you so much for testing. That's definitely an oversight on my end. Have you filled in the allowed guilds on your settings page with the ID of your group's Discord server?

I don't really know how to make this work without that. But it shouldn't crash either way. I'll try to fix that ^^

Le 18 février 2023 19 h 49 min 10 s UTC, "Paweł Kotiuk" @.***> a écrit :

I got Error:
obraz

[index] Error: Exception: Undefined constant "OCA\SocialLogin\Service\allowedGuilds" in file '/var/www/html/custom_apps/sociallogin/lib/Service/ProviderService.php' line 419 at <<closure>>

0. /var/www/html/lib/private/AppFramework/App.php line 172
  OC\AppFramework\Http\Dispatcher->dispatch(OCA\SocialLogin\ ... {}, "oauth")
1. /var/www/html/lib/private/Route/Router.php line 298
  OC\AppFramework\App::main("OCA\\SocialLogi ... r", "oauth", OC\AppFramework\ ... {}, ["discord","sociallogin.login.oauth"])
2. /var/www/html/lib/base.php line 1047
  OC\Route\Router->match("/apps/sociallogin/oauth/discord")
3. /var/www/html/index.php line 36
  OC::handleRequest()

GET /apps/sociallogin/oauth/discord?code=pDdWS6wcbjpOOFV0JQDXG30jv5V7qm&state=HA-UOV31RMWBCTXL8YJQIFA2KH74EZ6ND90PG5S
from 37.225.92.137 at 2023-02-18T19:45:32+00:00

-- Reply to this email directly or view it on GitHub: https://github.com/zorn-v/nextcloud-social-login/issues/390#issuecomment-1435755466 You are receiving this because you authored the thread.

Message ID: @.***>

pktiuk commented 1 year ago

This is how my config looks like: obraz Brak means None

zorn-v commented 1 year ago

Error: Exception: Undefined constant "OCA\SocialLogin\Service\allowedGuilds"

You just missed $ char somewhere, so allowedGuilds considered as constant.

kousu commented 1 year ago

Right. Obviously. :cold_sweat: I don't write PHP that often. fixed: https://github.com/zorn-v/nextcloud-social-login/pull/395/commits/ac5d3dfb97a2f70eef93d3c6a588fdadb65e7442

I'm a little confused how I didn't catch this. I have this code deployed on my server and I went to meetings and saw people logging in with it.

Anyway it's updated. Sorry for the trouble @pktiuk, would you run git pull to try again when you have a moment? Thanks!

pktiuk commented 1 year ago

image There is no group at all.

I also got an error, but it could be caused by not restarting NC correctly (after restarting container I could log in)

[PHP] Error: Error: exif_read_data(): File not supported at /var/www/html/lib/private/Metadata/Provider/ExifProvider.php#59 at <<closure>>

 0. <<closure>>
    OC\Log\ErrorHandler::onError(2, "exif_read_data(): File not supported", "/var/www/html/l ... p", 59)
 1. /var/www/html/lib/private/Metadata/Provider/ExifProvider.php line 59
    exif_read_data(null, "ANY_TAG", true)
 2. /var/www/html/lib/private/Metadata/MetadataManager.php line 68
    OC\Metadata\Provider\ExifProvider->execute(OC\Files\Node\File {})
 3. /var/www/html/lib/private/Metadata/FileEventListener.php line 101
    OC\Metadata\MetadataManager->generateMetadata(OC\Files\Node\File {}, "*** sensitive parameters replaced ***")
 4. /var/www/html/lib/private/EventDispatcher/ServiceEventListener.php line 87
    OC\Metadata\FileEventListener->handle(OCP\Files\Events\Node\NodeWrittenEvent {})
 5. /var/www/html/3rdparty/symfony/event-dispatcher/EventDispatcher.php line 251
    OC\EventDispatcher\ServiceEventListener->__invoke(OCP\Files\Events\Node\NodeWrittenEvent {}, "OCP\\Files\\Eve ... t", Symfony\Componen ... {})
 6. /var/www/html/3rdparty/symfony/event-dispatcher/EventDispatcher.php line 73
    Symfony\Component\EventDispatcher\EventDispatcher->callListeners([Closure {},Closure {}], "OCP\\Files\\Eve ... t", OCP\Files\Events\Node\NodeWrittenEvent {})
 7. /var/www/html/lib/private/EventDispatcher/EventDispatcher.php line 88
    Symfony\Component\EventDispatcher\EventDispatcher->dispatch(OCP\Files\Events\Node\NodeWrittenEvent {}, "OCP\\Files\\Eve ... t")
 8. /var/www/html/lib/private/EventDispatcher/EventDispatcher.php line 100
    OC\EventDispatcher\EventDispatcher->dispatch("OCP\\Files\\Eve ... t", OCP\Files\Events\Node\NodeWrittenEvent {})
 9. /var/www/html/lib/private/Files/Node/HookConnector.php line 118
    OC\EventDispatcher\EventDispatcher->dispatchTyped(OCP\Files\Events\Node\NodeWrittenEvent {})
10. /var/www/html/lib/private/legacy/OC_Hook.php line 106
    OC\Files\Node\HookConnector->postWrite(["/Nextcloud.png"])
11. /var/www/html/lib/private/Files/View.php line 641
    OC_Hook::emit("OC_Filesystem", "post_write", ["/Nextcloud.png"])
12. /var/www/html/lib/private/Files/View.php line 692
    OC\Files\View->emit_file_hooks_post(true, "/discord-634105 ... g")
13. /var/www/html/lib/private/Files/Node/File.php line 71
    OC\Files\View->file_put_contents("/discord-634105 ... g", null)
14. /var/www/html/lib/private/legacy/OC_Util.php line 257
    OC\Files\Node\File->putContent(null)
15. /var/www/html/lib/private/legacy/OC_Util.php line 216
    OC_Util::copyr("/var/www/html/core/skeleton", OC\Files\Node\Folder {})
16. /var/www/html/lib/private/User/Session.php line 553
    OC_Util::copySkeleton("*** sensitive parameters replaced ***", OC\Files\Node\Folder {})
17. /var/www/html/lib/private/User/Session.php line 403
    OC\User\Session->prepareUserLogin(true, "*** sensitive parameters replaced ***")
18. /var/www/html/custom_apps/sociallogin/lib/Service/ProviderService.php line 592
    OC\User\Session->completeLogin("*** sensitive parameters replaced ***")
19. /var/www/html/custom_apps/sociallogin/lib/Service/ProviderService.php line 448
    OCA\SocialLogin\Service\ProviderService->login("*** sensitive parameters replaced ***")
20. /var/www/html/custom_apps/sociallogin/lib/Service/ProviderService.php line 265
    OCA\SocialLogin\Service\ProviderService->auth("Hybridauth\\Provider\\Discord", ["https://nextcl ... "], "discord", "OAuth")
21. /var/www/html/custom_apps/sociallogin/lib/Controller/LoginController.php line 28
    OCA\SocialLogin\Service\ProviderService->handleDefault("discord")
22. /var/www/html/lib/private/AppFramework/Http/Dispatcher.php line 225
    OCA\SocialLogin\Controller\LoginController->oauth("discord")
23. /var/www/html/lib/private/AppFramework/Http/Dispatcher.php line 133
    OC\AppFramework\Http\Dispatcher->executeController(OCA\SocialLogin\ ... {}, "oauth")
24. /var/www/html/lib/private/AppFramework/App.php line 172
    OC\AppFramework\Http\Dispatcher->dispatch(OCA\SocialLogin\ ... {}, "oauth")
25. /var/www/html/lib/private/Route/Router.php line 298
    OC\AppFramework\App::main("OCA\\SocialLogi ... r", "oauth", OC\AppFramework\ ... {}, ["discord","sociallogin.login.oauth"])
26. /var/www/html/lib/base.php line 1047
    OC\Route\Router->match("/apps/sociallogin/oauth/discord")
27. /var/www/html/index.php line 36
    OC::handleRequest()

GET /apps/sociallogin/oauth/discord?code=wtJorNdskRDKFnZ2zmgRQN333Of9zj&state=HA-Z20DUGSMCWPVHL8OFEX1T54I6ANB9J3QY7KR
from 188.112.38.245 by discord-634105581567498952 at 2023-02-19T22:42:08+00:00
kousu commented 1 year ago

[PHP] Error: Error: exif_read_data(): File not supported at /var/www/html/lib/private/Metadata/Provider/ExifProvider.php#59 at <<closure>>

I get this one too, I think it's an unrelated problem. I think it's triggered by one of the skeleton files; NextCloud is trying to scan its metadata tags but failing:

``` {"reqId":"aJA5H5lcNck938xlgncC","level":3,"time":"2023-01-13T04:03:50+00:00","remoteAddr":"192.222.249.98","user":"admin","app":"PHP","method":"POST","url":"/index.php","message":"exif_read_data(): File not supported at /var/www/nextcloud/lib/private/Metadata/Provider/ExifProvider.php#59","userAgent":"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0","version":"25.0.2.3","exception":{"Exception":"Error","Message":"exif_read_data(): File not supported at /var/www/nextcloud/lib/private/Metadata/Provider/ExifProvider.php#59","Code":0,"Trace":[{"function":"onError","class":"OC\\Log\\ErrorHandler","type":"::"},{"file":"/var/www/nextcloud/lib/private/Metadata/Provider/ExifProvider.php","line":59,"function":"exif_read_data"},{"file":"/var/www/nextcloud/lib/private/Metadata/MetadataManager.php","line":68,"function":"execute","class":"OC\\Metadata\\Provider\\ExifProvider","type":"->"},{"file":"/var/www/nextcloud/lib/private/Metadata/FileEventListener.php","line":101,"function":"generateMetadata","class":"OC\\Metadata\\MetadataManager","type":"->"},{"file":"/var/www/nextcloud/lib/private/EventDispatcher/ServiceEventListener.php","line":87,"function":"handle","class":"OC\\Metadata\\FileEventListener","type":"->"},{"file":"/var/www/nextcloud/3rdparty/symfony/event-dispatcher/EventDispatcher.php","line":251,"function":"__invoke","class":"OC\\EventDispatcher\\ServiceEventListener","type":"->"},{"file":"/var/www/nextcloud/3rdparty/symfony/event-dispatcher/EventDispatcher.php","line":73,"function":"callListeners","class":"Symfony\\Component\\EventDispatcher\\EventDispatcher","type":"->"},{"file":"/var/www/nextcloud/lib/private/EventDispatcher/EventDispatcher.php","line":88,"function":"dispatch","class":"Symfony\\Component\\EventDispatcher\\EventDispatcher","type":"->"},{"file":"/var/www/nextcloud/lib/private/EventDispatcher/EventDispatcher.php","line":100,"function":"dispatch","class":"OC\\EventDispatcher\\EventDispatcher","type":"->"},{"file":"/var/www/nextcloud/lib/private/Files/Node/HookConnector.php","line":118,"function":"dispatchTyped","class":"OC\\EventDispatcher\\EventDispatcher","type":"->"},{"file":"/var/www/nextcloud/lib/private/legacy/OC_Hook.php","line":106,"function":"postWrite","class":"OC\\Files\\Node\\HookConnector","type":"->"},{"file":"/var/www/nextcloud/lib/private/Files/View.php","line":641,"function":"emit","class":"OC_Hook","type":"::"},{"file":"/var/www/nextcloud/lib/private/Files/View.php","line":692,"function":"emit_file_hooks_post","class":"OC\\Files\\View","type":"->"},{"file":"/var/www/nextcloud/lib/private/Files/Node/File.php","line":71,"function":"file_put_contents","class":"OC\\Files\\View","type":"->"},{"file":"/var/www/nextcloud/lib/private/legacy/OC_Util.php","line":257,"function":"putContent","class":"OC\\Files\\Node\\File","type":"->"},{"file":"/var/www/nextcloud/lib/private/legacy/OC_Util.php","line":216,"function":"copyr","class":"OC_Util","type":"::"},{"file":"/var/www/nextcloud/lib/private/User/Session.php","line":553,"function":"copySkeleton","class":"OC_Util","type":"::"},{"file":"/var/www/nextcloud/lib/private/User/Session.php","line":403,"function":"prepareUserLogin","class":"OC\\User\\Session","type":"->"},{"file":"/var/www/nextcloud/lib/private/User/Session.php","line":616,"function":"completeLogin","class":"OC\\User\\Session","type":"->","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/nextcloud/lib/private/User/Session.php","line":355,"function":"loginWithPassword","class":"OC\\User\\Session","type":"->","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/nextcloud/lib/private/Setup.php","line":433,"function":"login","class":"OC\\User\\Session","type":"->","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/nextcloud/core/Controller/SetupController.php","line":69,"function":"install","class":"OC\\Setup","type":"->","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/nextcloud/lib/base.php","line":980,"function":"run","class":"OC\\Core\\Controller\\SetupController","type":"->","args":["*** sensitive parameters replaced ***"]},{"file":"/var/www/nextcloud/index.php","line":36,"function":"handleRequest","class":"OC","type":"::"}],"File":"/var/www/nextcloud/lib/private/Log/ErrorHandler.php","Line":92,"CustomMessage":"--"}} ```

So

GET /apps/sociallogin/oauth/discord?code=wtJorNdskRDKFnZ2zmgRQN333Of9zj&state=HA-Z20DUGSMCWPVHL8OFEX1T54I6ANB9J3QY7KR from 188.112.38.245 by discord-634105581567498952 at 2023-02-19T22:42:08+00:00

is the only interesting log, and it doesn't say much. :thinking:


I was thinking about this and I realized that on mine I have enabled a bot user on my OAuth app, and I invited that bot user to my guild, with, well, probably too many permissions:

Screenshot_20230222_142002

But I tried removing it, and it still behaves itself for me

Screenshot_20230222_142132

So I don't think that's the issue.


What version of PHP are you on? I'm using 7.4 (old, I know, but it's what my distro happens to have at the moment).


You have been very helpful @pktiuk. I do not know what's wrong. I won't bother you any more if you just want to delete and reinstall the basic sociallogin app. I'll be sure to let you know if I make more progress though in the future.

pktiuk commented 1 year ago

I use docker from: https://github.com/nextcloud/all-in-one It has version: 8.0.26

pktiuk commented 1 year ago

I won't bother you any more if you just want to delete and reinstall the basic sociallogin app. I'll be sure to let you know if I make more progress though in the future.

I can still help you with this functionality. Helping you is in my best interest. I think this feature will be incredibly useful in my organization :)

Thelvaen commented 11 months ago

I am also really interested in mapping roles in a specific Discord guild directly to a group for a group I'm belonging to.

pktiuk commented 7 months ago

I think this issue can be closed now.
Reading roles in groups was implemented in https://github.com/zorn-v/nextcloud-social-login/commit/eb1ab8890c815691463888d9309c137898365b04 :heart: :tada: