├── LICENSE ├── README.md ├── composer.json └── src ├── MastodonProvider.php └── MastodonServiceProvider.php /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 kawax 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Socialite for Mastodon 2 | 3 | https://github.com/mastodon/mastodon 4 | 5 | ## Requirements 6 | - PHP >= 8.0 7 | 8 | > No version restrictions. It may stop working in future versions. 9 | 10 | ## Install 11 | ``` 12 | composer require revolution/socialite-mastodon 13 | ``` 14 | 15 | ### config/services.php 16 | 17 | ```php 18 | 'mastodon' => [ 19 | 'domain' => env('MASTODON_DOMAIN'), 20 | 'client_id' => env('MASTODON_ID'), 21 | 'client_secret' => env('MASTODON_SECRET'), 22 | 'redirect' => env('MASTODON_REDIRECT'), 23 | 'scope' => ['read', 'write'], 24 | ], 25 | ``` 26 | 27 | ### .env 28 | ``` 29 | MASTODON_DOMAIN=https://localhost 30 | MASTODON_ID= 31 | MASTODON_SECRET= 32 | MASTODON_REDIRECT=https://localhost/callback 33 | ``` 34 | 35 | ## Create App and get the client_id & client_secret 36 | 37 | 1. Go to your Mastodon's user preferences page. 38 | 2. Go to development page. 39 | 3. Create new application. 40 | 4. Get `Client key` and `Client secret` 41 | 42 | ## Usage 43 | 44 | ### Use one instance 45 | routes/web.php 46 | ```php 47 | Route::get('/', [MastodonController::class, 'index']); 48 | Route::get('callback', [MastodonController::class, 'callback']); 49 | ``` 50 | 51 | MastodonController 52 | 53 | ```php 54 | namespace App\Http\Controllers; 55 | 56 | use Illuminate\Http\Request; 57 | use Laravel\Socialite\Facades\Socialite; 58 | 59 | class MastodonController extends Controller 60 | { 61 | public function index() 62 | { 63 | return Socialite::driver('mastodon')->redirect(); 64 | } 65 | 66 | public function callback() 67 | { 68 | $user = Socialite::driver('mastodon')->user(); 69 | dd($user); 70 | } 71 | } 72 | ``` 73 | 74 | Set scopes 75 | ```php 76 | return Socialite::driver('mastodon') 77 | ->setScopes(config('services.mastodon.scope', ['read'])) 78 | ->redirect(); 79 | ``` 80 | 81 | https://docs.joinmastodon.org/api/oauth-scopes/ 82 | 83 | ### Customize domain example 84 | 85 | Mastodon API for Laravel 86 | https://github.com/invokable/laravel-mastodon-api 87 | 88 | ```php 89 | use Illuminate\Http\Request; 90 | use Laravel\Socialite\Facades\Socialite; 91 | use Revolution\Mastodon\Facades\Mastodon; 92 | use App\Models\Server; 93 | 94 | public function login(Request $request) 95 | { 96 | //input domain by user 97 | $domain = $request->input('domain'); 98 | 99 | //get app info. domain, client_id, client_secret ... 100 | //Server is Eloquent Model 101 | $server = Server::where('domain', $domain)->first(); 102 | 103 | if (empty($server)) { 104 | //create new app 105 | $info = Mastodon::domain($domain)->createApp(client_name: 'my-app', redirect_uris: 'https://example.com/callback', scopes: 'read write'); 106 | 107 | //save app info 108 | $server = Server::create([ 109 | 'domain' => $domain, 110 | 'client_id' => $info['client_id'], 111 | 'client_secret' => $info['client_secret'], 112 | ]); 113 | } 114 | 115 | session(['mastodon_domain' => $domain]); 116 | 117 | return Socialite::driver('mastodon')->with(['domain' => $domain, 'client_id' => $server->client_id])->redirect(); 118 | } 119 | 120 | public function callback() 121 | { 122 | $domain = session('mastodon_domain'); 123 | $server = Server::where('domain', $domain)->first(); 124 | 125 | $user = Socialite::driver('mastodon')->with(['domain' => $domain, 'client_id' => $server->client_id, 'client_secret' => $server->client_secret])->user(); 126 | dd($user); 127 | } 128 | ``` 129 | 130 | ## LICENCE 131 | MIT 132 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "revolution/socialite-mastodon", 3 | "description": "Socialite for Mastodon", 4 | "keywords": [ 5 | "mastodon", 6 | "socialite", 7 | "laravel" 8 | ], 9 | "license": "MIT", 10 | "require": { 11 | "php": "^8.0", 12 | "ext-json": "*", 13 | "laravel/socialite": "*" 14 | }, 15 | "require-dev": { 16 | "orchestra/testbench": "^9.0||^10.0", 17 | "revolution/laravel-mastodon-api": "^3.1", 18 | "laravel/pint": "^1.22" 19 | }, 20 | "autoload": { 21 | "psr-4": { 22 | "Revolution\\Socialite\\Mastodon\\": "src" 23 | } 24 | }, 25 | "autoload-dev": { 26 | "psr-4": { 27 | "Tests\\": "tests/" 28 | } 29 | }, 30 | "authors": [ 31 | { 32 | "name": "kawax", 33 | "email": "kawaxbiz@gmail.com" 34 | } 35 | ], 36 | "extra": { 37 | "laravel": { 38 | "providers": [ 39 | "Revolution\\Socialite\\Mastodon\\MastodonServiceProvider" 40 | ] 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/MastodonProvider.php: -------------------------------------------------------------------------------- 1 | domain().'/oauth/authorize/'; 33 | 34 | return $this->buildAuthUrlFromBase($url, $state); 35 | } 36 | 37 | /** 38 | * {@inheritdoc} 39 | */ 40 | protected function getCodeFields($state = null): array 41 | { 42 | $fields = parent::getCodeFields($state); 43 | 44 | unset($fields['client_secret']); 45 | 46 | return $this->updateFields($fields); 47 | } 48 | 49 | /** 50 | * {@inheritdoc} 51 | */ 52 | protected function getTokenUrl(): string 53 | { 54 | return $this->domain().'/oauth/token'; 55 | } 56 | 57 | /** 58 | * {@inheritdoc} 59 | */ 60 | protected function getTokenFields($code): array 61 | { 62 | return $this->updateFields(parent::getTokenFields($code)); 63 | } 64 | 65 | /** 66 | * {@inheritdoc} 67 | */ 68 | protected function getUserByToken($token) 69 | { 70 | $url = $this->domain().'/api/v1/accounts/verify_credentials'; 71 | 72 | $response = $this->getHttpClient()->get($url, [ 73 | 'headers' => [ 74 | 'Authorization' => 'Bearer '.$token, 75 | ], 76 | ]); 77 | 78 | return json_decode($response->getBody(), true); 79 | } 80 | 81 | /** 82 | * {@inheritdoc} 83 | */ 84 | protected function mapUserToObject(array $user): User 85 | { 86 | $domain = $this->domain(); 87 | $url_host = parse_url($domain, PHP_URL_HOST) ?? ''; 88 | 89 | return (new User)->setRaw($user)->map([ 90 | 'id' => $user['id'], 91 | 'nickname' => $user['username'] ?? '', 92 | 'name' => $user['display_name'] ?? '', 93 | 'email' => '', 94 | 'avatar' => $user['avatar'] ?? '', 95 | 'server' => $domain, 96 | 'user_identifier' => '@'.($user['username'] ?? '').'@'.$url_host, 97 | 'acct' => ($user['username'] ?? '').'@'.$url_host, 98 | ]); 99 | } 100 | 101 | protected function domain(): string 102 | { 103 | return Str::rtrim($this->parameters['domain'] ?? Config::get('services.mastodon.domain'), '/'); 104 | } 105 | 106 | protected function updateFields($fields): array 107 | { 108 | unset($fields['domain']); 109 | 110 | return $fields; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/MastodonServiceProvider.php: -------------------------------------------------------------------------------- 1 |