podcasthosting / socialiteprovider-podcastde
podcast.de OAuth2 Provider for Laravel Socialite
Package info
github.com/podcasthosting/SocialiteProvider-podcastde
pkg:composer/podcasthosting/socialiteprovider-podcastde
Requires
- php: ^8.3
- ext-json: *
- socialiteproviders/manager: ^4.4
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- orchestra/testbench: ^9.0|^10.0
- pestphp/pest: ^3.0
- phpstan/phpstan: ^2.1
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
OAuth2 driver for logging in via podcast.de, built on top of SocialiteProviders/Manager.
Requirements
- PHP
^8.3 socialiteproviders/manager^4.4
Installation
composer require podcasthosting/socialiteprovider-podcastde
Configuration
1. .env
PODCASTDE_CLIENT_ID=your-client-id PODCASTDE_CLIENT_SECRET=your-client-secret PODCASTDE_REDIRECT_URI=https://your-app.test/auth/podcastde/callback
2. config/services.php
'podcastde' => [ 'client_id' => env('PODCASTDE_CLIENT_ID'), 'client_secret' => env('PODCASTDE_CLIENT_SECRET'), 'redirect' => env('PODCASTDE_REDIRECT_URI'), ],
3. Register the event listener
In app/Providers/EventServiceProvider.php:
protected $listen = [ \SocialiteProviders\Manager\SocialiteWasCalled::class => [ \Podcasthosting\Podcastde\PodcastdeExtendSocialite::class, ], ];
Usage
use Laravel\Socialite\Facades\Socialite; Route::get('/auth/podcastde', fn () => Socialite::driver('podcastde')->redirect()); Route::get('/auth/podcastde/callback', function () { $user = Socialite::driver('podcastde')->user(); // $user->getId(), $user->getNickname(), $user->getName(), // $user->getEmail(), $user->getAvatar(), $user->token, ... });
Scopes
The provider requests the user-read-only scope by default. The scope names are available
as Podcasthosting\Podcastde\Scope enum.
To additionally request read access to the podcasts the user has claimed on podcast.de
(titles, feed and web URLs), call withPodcastsReadOnly():
return Socialite::driver('podcastde')->withPodcastsReadOnly()->redirect();
podcasts-read-only is optional for the user: it can be deselected on the podcast.de consent
screen. With the scope granted, GET https://www.podcast.de/api/oauth/podcasts (Bearer token)
returns the claimed podcasts as {"data": [{"id", "title", "slug", "rss", "web", "owner_type"}]}.
The granted scopes are taken from the scopes claim of the access token (Laravel Passport
does not return them in the token response) and are available via $user->approvedScopes:
use Podcasthosting\Podcastde\Scope; $user = Socialite::driver('podcastde')->user(); if (in_array(Scope::PodcastsReadOnly->value, $user->approvedScopes, true)) { // access token may list the user's podcasts via /api/oauth/podcasts }
User data
User details are fetched from https://www.podcast.de/api/oauth/me, which returns the serialised
user model. The Socialite user is mapped as follows:
| Socialite | podcast.de |
|---|---|
id |
id |
nickname |
username |
name |
first_name last_name, falling back to username |
email |
email |
avatar |
avatar_url (null if the account has no profile picture) |
Missing fields map to null. All attributes returned by the API are available via getRaw().
Refreshing tokens
$token = Socialite::driver('podcastde')->refreshToken($user->refreshToken); // $token->token, $token->refreshToken, $token->expiresIn, $token->approvedScopes
If podcast.de does not rotate the refresh token, the one you passed in is kept.
PKCE
PKCE (RFC 7636) is enabled by default with S256 as code challenge method. The provider stores
the code_verifier in the Laravel session during redirect() and submits it automatically in the
token exchange request. No additional configuration is required.
If you need to disable PKCE for any reason, extend the provider and set protected $usesPKCE = false;.
Testing
The test suite uses Pest and Orchestra Testbench:
composer test # Pest composer analyse # PHPStan (level max) composer lint # php-cs-fixer dry run, `composer format` applies fixes composer coverage # code coverage (min. 100 %, needs PCOV or Xdebug) composer mutate # mutation testing (min. 100 % score) composer check # lint, analyse, test
tests/Unit– the provider in isolation (authorization URL, scopes, PKCE, token exchange, user mapping, approved scopes)tests/Feature– the full login flow throughSocialite::driver('podcastde')inside a Laravel applicationtests/ArchTest.php– architecture rules (strict types, no debug calls, class contracts)
License
MIT