Search by

podcasthosting / socialiteprovider-podcastde

podcasthosting

podcast.de OAuth2 Provider for Laravel Socialite

Package info

github.com/podcasthosting/SocialiteProvider-podcastde

Homepage

pkg:composer/podcasthosting/socialiteprovider-podcastde

Statistics

Installs: 91

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.1 2026-10-12 17:38 UTC

This package is auto-updated.

Last update: 2026-10-12 17:40:39 UTC


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 through Socialite::driver('podcastde') inside a Laravel application
  • tests/ArchTest.php – architecture rules (strict types, no debug calls, class contracts)

License

MIT