Initial commit

This commit is contained in:
Martin Bean 2020-05-22 13:32:55 +01:00
commit d4fc0f73a2
6 changed files with 259 additions and 0 deletions

9
.editorconfig Normal file
View File

@ -0,0 +1,9 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/vendor
composer.lock

89
README.md Normal file
View File

@ -0,0 +1,89 @@
# 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._
## Installation
```
composer require martinbean/socialite-discord-provider
```
## Usage
The package registers a Socialite driver with the name of `discord`.
Before using the driver, create an OAuth application in Discords 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.
```php
<?php
// config/services.php
return [
// Any other services
'discord' => [
'client_id' => env('DISCORD_CLIENT_ID'),
'client_secret' => env('DISCORD_CLIENT_SECRET'),
'redirect' => '/auth/discord/callback',
],
];
```
The `redirect` value will need to match a redirect URL in your Discord application settings. It can be relative as above.
Then, create a controller to redirect and handle the token callback:
```php
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Laravel\Socialite\Facades\Socialite;
class DiscordController extends Controller
{
/**
* Redirect the user to the Discord authentication page.
*
* @return \Illuminate\Http\Response
*/
public function redirectToProvider()
{
return Socialite::driver('discord')->redirect();
}
/**
* Obtain the user information from Discord.
*
* @return \Illuminate\Http\Response
*/
public function handleProviderCallback()
{
$user = Socialite::driver('discord')->user();
// $user->token;
}
}
```
### Scopes
Discord supports various scopes. You can find a list here: https://discord.com/developers/docs/topics/oauth2#shared-resources-oauth2-scopes
To request additional scopes when authenticating, you can use the `scopes` method before redirecting:
```php
return Socialite::driver('discord')
->scopes(['guilds', 'messages.read'])
->redirect();
```
## Issues
If you have any problems using this package, please open an issue on the [GitHub repository][2].
[1] https://laravel.com/docs/master/socialite
[2]: https://github.com/martinbean/socialite-discord-provider

43
composer.json Normal file
View File

@ -0,0 +1,43 @@
{
"name": "martinbean/socialite-discord-provider",
"description": "A Discord provider for Laravel Socialite.",
"version": "1.0",
"type": "library",
"keywords": [
"laravel",
"socialite",
"discord",
"oauth"
],
"readme": "README.md",
"license": "MIT",
"authors": [
{
"name": "Martin Bean",
"email": "martin@martinbean.co.uk",
"homepage": "https://martinbean.co.uk"
}
],
"support": {
"issues": "https://github.com/martinbean/socialite-discord-provider/issues",
"source": "https://github.com/martinbean/socialite-discord-provider"
},
"require": {
"laravel/socialite": "^4.0"
},
"autoload": {
"psr-4": {
"MartinBean\\Laravel\\Socialite\\": "src/"
}
},
"config": {
"sort-packages": true
},
"extra": {
"laravel": {
"providers": [
"MartinBean\\Laravel\\Socialite\\DiscordServiceProvider"
]
}
}
}

82
src/DiscordProvider.php Normal file
View File

@ -0,0 +1,82 @@
<?php
namespace MartinBean\Laravel\Socialite;
use Laravel\Socialite\Two\AbstractProvider;
use Laravel\Socialite\Two\ProviderInterface;
use Laravel\Socialite\Two\User;
class DiscordProvider extends AbstractProvider implements ProviderInterface
{
/**
* {@inheritDoc}
*/
protected $scopes = [
'email',
'identify',
];
/**
* {@inheritDoc}
*/
protected $scopeSeparator = ' ';
/**
* {@inheritDoc}
*/
protected function getAuthUrl($state)
{
return $this->buildAuthUrlFromBase('https://discord.com/api/oauth2/authorize', $state);
}
/**
* {@inheritDoc}
*/
protected function getTokenUrl()
{
return 'https://discord.com/api/oauth2/token';
}
/**
* {@inheritDoc}
*/
protected function getUserByToken($token)
{
$userUrl = 'https://discord.com/api/users/@me';
$response = $this->getHttpClient()->get($userUrl, [
'headers' => [
'Authorization' => 'Bearer '.$token,
],
]);
return json_decode($response->getBody(), true);
}
/**
* {@inheritDoc}
*/
protected function mapUserToObject(array $user)
{
return (new User())->setRaw($user)->map([
'id' => $user['id'],
'name' => $user['username'],
'email' => $user['email'],
'avatar' => sprintf('https://cdn.discordapp.com/avatars/%s/%s.png', $user['id'], $user['avatar']),
]);
}
/**
* {@inheritDoc}
*/
protected function getTokenFields($code)
{
return [
'client_id' => $this->clientId,
'client_secret' => $this->clientSecret,
'code' => $code,
'grant_type' => 'authorization_code',
'redirect_uri' => $this->redirectUrl,
];
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace MartinBean\Laravel\Socialite;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Arr;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
use Laravel\Socialite\Facades\Socialite;
class DiscordServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
Socialite::extend('discord', function (Application $app) {
$config = $app->make('config')->get('services.discord');
$redirect = value(Arr::get($config, 'redirect'));
return new DiscordProvider(
$app->make('request'),
Arr::get($config, 'client_id', ''),
Arr::get($config, 'client_secret', ''),
Str::startsWith($redirect, '/') ? $app->make('url')->to($redirect) : $redirect,
Arr::get($config, 'guzzle', [])
);
});
}
}