diff --git a/README.md b/README.md index a0fdf87..d3550cc 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,9 @@ # Discord provider for Laravel Socialite -A provider for [Laravel Socialite][1] that allows authentication as a Discord user. -_Authenticating as a bot is currently not supported._ +A provider for [Laravel Socialite][1] that allows authentication as a Discord user or bot. ## Installation ``` -composer require martinbean/socialite-discord-provider +composer require martinbean/socialite-discord-provider:^1.1 ``` ## Usage @@ -13,8 +12,7 @@ The package registers a Socialite driver with the name of `discord`. Before using the driver, create an OAuth application in Discord’s developer portal: https://discord.com/developers/applications -Set your client ID and client secret as environment variables, and then reference them in your **config/services.php** file. -You will also need to add a redirect URL to your application. +Set your client ID and client secret as environment variables, and then reference them in your **config/services.php** file. You will also need to add a redirect URL to your application if you intend to authenticate as a user. ```php redirect(); ``` +### Authenticating as a bot +Discord allows you to add “bots” to guilds (servers). This is a modified OAuth flow, where you are redirected to Discord to confirm the guild you wish to add a bot to. There is no redirect back to your application when you authorize the request. + +You can authenticate as a bot by using the `bot` method before redirecting: + +```php +bot()->redirect(); + } +} +``` + +If you know the guild ID you wish to add your bot to, you may specify it with the `guild` method: + +```php +return Socialite::driver('discord') + ->bot() + ->guild($guildId) + ->redirect(); +``` + +Additionally, you can disable the guild select: + +```php +return Socialite::driver('discord') + ->bot() + ->guild($guildId) + ->disableGuildSelect() + ->redirect(); +``` + +**Note:** if you try and disable guild selection without specifying a guild, the package will throw a `GuildRequiredException` instance. + ## Issues If you have any problems using this package, please open an issue on the [GitHub repository][2]. diff --git a/composer.json b/composer.json index 55a9173..92dda9d 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "martinbean/socialite-discord-provider", "description": "A Discord provider for Laravel Socialite.", - "version": "1.0", + "version": "1.1.0", "type": "library", "keywords": [ "laravel", @@ -23,6 +23,7 @@ "source": "https://github.com/martinbean/socialite-discord-provider" }, "require": { + "facade/ignition-contracts": "^1.0", "laravel/socialite": "^4.0" }, "autoload": { diff --git a/src/BotRedirectBuilder.php b/src/BotRedirectBuilder.php new file mode 100644 index 0000000..cdbaf99 --- /dev/null +++ b/src/BotRedirectBuilder.php @@ -0,0 +1,139 @@ +clientId = $clientId; + } + + /** + * Set the permissions to request. + * + * @param int $permissions + * @return $this + */ + public function permissions(int $permissions) + { + $this->permissions = $permissions; + + return $this; + } + + /** + * Pre-fill the dropdown picker with a guild for the user. + * + * @param string|int $guild + * @return $this + */ + public function guild($guild) + { + $this->guild = (string) $guild; + + return $this; + } + + /** + * Disallow the user from changing the guild dropdown. + * + * @return $this + */ + public function disableGuildSelect() + { + $this->disableGuildSelect = true; + + return $this; + } + + /** + * Redirect the user of the application to the provider's authentication screen. + * + * @return \Illuminate\Http\RedirectResponse + */ + public function redirect() + { + return new RedirectResponse($this->getAuthUrl()); + } + + /** + * Get the authentication URL for the provider. + * + * @param string $url + * @return string + */ + protected function buildAuthUrlFromBase($url) + { + return $url.'?'.http_build_query($this->getCodeFields(), '', '&', PHP_QUERY_RFC1738); + } + + /** + * Get the GET parameters for the code request. + * + * @return array + * + * @throws \MartinBean\Laravel\Socialite\Exceptions\GuildRequiredException + */ + protected function getCodeFields() + { + if ($this->disableGuildSelect && ! $this->guild) { + throw new GuildRequiredException(); + } + + return [ + 'client_id' => $this->clientId, + 'scope' => 'bot', + 'permissions' => $this->permissions, + 'guild_id' => $this->guild, + 'disable_guild_select' => $this->disableGuildSelect ? 'true' : 'false', + ]; + } + + /** + * Get the authentication URL for the provider. + * + * @return string + */ + protected function getAuthUrl() + { + return $this->buildAuthUrlFromBase('https://discord.com/api/oauth2/authorize'); + } +} diff --git a/src/DiscordProvider.php b/src/DiscordProvider.php index 358094d..51cb644 100644 --- a/src/DiscordProvider.php +++ b/src/DiscordProvider.php @@ -21,6 +21,16 @@ class DiscordProvider extends AbstractProvider implements ProviderInterface */ protected $scopeSeparator = ' '; + /** + * Create a new bot redirect. + * + * @return \MartinBean\Laravel\Socialite\BotRedirectBuilder + */ + public function bot() + { + return new BotRedirectBuilder($this->clientId); + } + /** * {@inheritDoc} */ diff --git a/src/DiscordServiceProvider.php b/src/DiscordServiceProvider.php index 6e8774f..56e4fd1 100644 --- a/src/DiscordServiceProvider.php +++ b/src/DiscordServiceProvider.php @@ -24,8 +24,8 @@ class DiscordServiceProvider extends ServiceProvider return new DiscordProvider( $app->make('request'), - Arr::get($config, 'client_id', ''), - Arr::get($config, 'client_secret', ''), + $config['client_id'], + $config['client_secret'], Str::startsWith($redirect, '/') ? $app->make('url')->to($redirect) : $redirect, Arr::get($config, 'guzzle', []) ); diff --git a/src/Exceptions/GuildRequiredException.php b/src/Exceptions/GuildRequiredException.php new file mode 100644 index 0000000..9a088fb --- /dev/null +++ b/src/Exceptions/GuildRequiredException.php @@ -0,0 +1,29 @@ +setSolutionDescription('Call `guild($guildId)` before redirecting.'); + } +}