Skip to content

Commit

Permalink
FeedGenerator: Add a callback hook to validate requests
Browse files Browse the repository at this point in the history
  • Loading branch information
puklipo committed Nov 25, 2024
1 parent 540c00a commit 847bffc
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 4 deletions.
51 changes: 51 additions & 0 deletions src/FeedGenerator/FeedGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
namespace Revolution\Bluesky\FeedGenerator;

use BackedEnum;
use Closure;
use Illuminate\Http\Request;
use Revolution\Bluesky\Socialite\Key\JsonWebToken;
use Revolution\Bluesky\Support\DID;

use function Illuminate\Support\enum_value;
Expand All @@ -12,6 +14,8 @@ final class FeedGenerator
{
protected static array $algos;

protected static ?Closure $validateAuthUsing = null;

/**
* Register FeedGenerator algorithm.
*
Expand Down Expand Up @@ -80,4 +84,51 @@ public static function flush(): void
{
self::$algos = [];
}

/**
* ```
* // AppServiceProvider::boot()
*
* use Illuminate\Http\Request;
* use Revolution\Bluesky\FeedGenerator\FeedGenerator;
* use Revolution\Bluesky\Socialite\Key\JsonWebToken;
* use Firebase\JWT\JWT;
*
* FeedGenerator::validateAuthUsing(function (Request $request): ?string {
* $jwt = JsonWebToken::decode($request->bearerToken());
* $header = data_get($jwt, 'header');
*
* $payload = data_get($jwt, 'payload');
* $did = data_get($payload, 'iss');
*
* $sig = data_get($jwt, 'sig');
* $sig = JWT::urlsafeB64Decode($sig);
*
* // ...
*
* // Returns the user's DID on success, or null on failure.
* return $did;
* });
* ```
*
* @param callable(Request $request): ?string $callback
*/
public static function validateAuthUsing(callable $callback): void
{
self::$validateAuthUsing = $callback;
}

/**
* Normally, validation is recommended here, but it is skipped. If you want to validate strictly, add callback with {@link validateAuthUsing()}.
*
* @link https://github.com/bluesky-social/feed-generator/blob/main/src/auth.ts
*/
public static function validateAuth(Request $request): ?string
{
if (is_callable(self::$validateAuthUsing)) {
return call_user_func(self::$validateAuthUsing, $request);
}

return data_get(JsonWebToken::decode($request->bearerToken()), 'payload.iss');
}
}
5 changes: 1 addition & 4 deletions src/FeedGenerator/Http/FeedSkeletonController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use Illuminate\Http\Request;
use Revolution\AtProto\Lexicon\Enum\Feed;
use Revolution\Bluesky\FeedGenerator\FeedGenerator;
use Revolution\Bluesky\Socalite\Key\JsonWebToken;
use Revolution\Bluesky\Support\AtUri;

class FeedSkeletonController
Expand All @@ -29,11 +28,9 @@ public function __invoke(Request $request): mixed

/**
* Requesting user's DID.
*
* Skip verify.
*/
protected function userDid(Request $request): ?string
{
return data_get(JsonWebToken::decode($request->bearerToken()), 'payload.iss');
return FeedGenerator::validateAuth($request);
}
}
17 changes: 17 additions & 0 deletions tests/Feature/FeedGenerator/FeedGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Tests\Feature\FeedGenerator;

use Illuminate\Http\Request;
use Revolution\Bluesky\FeedGenerator\FeedGenerator;
use Tests\TestCase;

Expand Down Expand Up @@ -64,4 +65,20 @@ public function test_feed_atproto_did(): void

$response->assertSuccessful();
}

public function test_validate_auth_using()
{
FeedGenerator::validateAuthUsing(function (Request $request) {
return 'did';
});

FeedGenerator::register('test', function (?int $limit, ?string $cursor): array {
return ['feed' => [['post' => 'at://']]];
});

$response = $this->get(route('bluesky.feed.skeleton', ['feed' => 'at://did:/app.bsky.feed.generator/test']));

$response->assertSuccessful();
$response->assertJson(['feed' => [['post' => 'at://']]]);
}
}

0 comments on commit 847bffc

Please sign in to comment.