Skip to content

Commit 32582fa

Browse files
committed
feat(routes): auto-register Apple Sign In routes and controller
- Add AppleSignInController with redirect and callback actions - Auto-register routes (apple/redirect and apple/callback) via ServiceProvider - Routes can be disabled or customized via config - Apple callback expects form POST with user data - All AC boxes complete: routes auto-register, paths customizable, can be disabled via config
1 parent 5e7a6e1 commit 32582fa

File tree

5 files changed

+148
-0
lines changed

5 files changed

+148
-0
lines changed

config/services.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,11 @@
66
"redirect" => env("SIGN_IN_WITH_APPLE_REDIRECT"),
77
"client_id" => env("SIGN_IN_WITH_APPLE_CLIENT_ID"),
88
"client_secret" => env("SIGN_IN_WITH_APPLE_CLIENT_SECRET"),
9+
// Auto-register package routes
10+
"routes" => [
11+
"enabled" => true,
12+
"redirect_route" => "apple/redirect",
13+
"callback_route" => "apple/callback",
14+
],
915
],
1016
];

routes/web.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
use GeneaLabs\LaravelSignInWithApple\Http\Controllers\AppleSignInController;
4+
use Illuminate\Support\Facades\Route;
5+
6+
Route::group([
7+
'middleware' => ['web'],
8+
], function () {
9+
$redirectPath = config('services.sign_in_with_apple.routes.redirect_route', 'apple/redirect');
10+
$callbackPath = config('services.sign_in_with_apple.routes.callback_route', 'apple/callback');
11+
12+
Route::get($redirectPath, [AppleSignInController::class, 'redirect'])
13+
->name('apple.redirect');
14+
15+
Route::post($callbackPath, [AppleSignInController::class, 'callback'])
16+
->name('apple.callback');
17+
});
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace GeneaLabs\LaravelSignInWithApple\Http\Controllers;
4+
5+
use Illuminate\Http\RedirectResponse;
6+
use Illuminate\Http\Request;
7+
use Illuminate\Routing\Controller;
8+
use Laravel\Socialite\Facades\Socialite;
9+
10+
class AppleSignInController extends Controller
11+
{
12+
/**
13+
* Redirect to Apple for authentication.
14+
*/
15+
public function redirect(): RedirectResponse
16+
{
17+
return Socialite::driver('sign-in-with-apple')
18+
->scopes(['name', 'email'])
19+
->redirect();
20+
}
21+
22+
/**
23+
* Handle the callback from Apple.
24+
*
25+
* Override this controller or bind your own to customize user resolution.
26+
*/
27+
public function callback(Request $request)
28+
{
29+
$user = Socialite::driver('sign-in-with-apple')->user();
30+
31+
// Default: return the Socialite user.
32+
// Apps should override this controller or use their own route to persist users.
33+
return $user;
34+
}
35+
}

src/Providers/ServiceProvider.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class ServiceProvider extends LaravelServiceProvider
1212

1313
public function boot()
1414
{
15+
$this->loadRoutesIf(config('services.sign_in_with_apple.routes.enabled', true));
1516
$this->bootSocialiteDriver();
1617
$this->bootBladeDirective();
1718
}
@@ -29,6 +30,16 @@ protected function registerConfiguration()
2930
);
3031
}
3132

33+
/**
34+
* Load package routes if enabled in config.
35+
*/
36+
protected function loadRoutesIf(bool $enabled): void
37+
{
38+
if ($enabled) {
39+
$this->loadRoutesFrom(__DIR__ . '/../../routes/web.php');
40+
}
41+
}
42+
3243
public function bootSocialiteDriver()
3344
{
3445
$socialite = $this->app->make(Factory::class);
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
namespace GeneaLabs\LaravelSignInWithApple\Tests\Unit;
4+
5+
use GeneaLabs\LaravelSignInWithApple\Http\Controllers\AppleSignInController;
6+
use GeneaLabs\LaravelSignInWithApple\Tests\UnitTestCase;
7+
8+
class RouteRegistrationTest extends UnitTestCase
9+
{
10+
public function testAppleRedirectRouteIsRegistered(): void
11+
{
12+
$routes = $this->app['router']->getRoutes();
13+
14+
$redirectRoute = $routes->getByName('apple.redirect');
15+
16+
$this->assertNotNull($redirectRoute);
17+
$this->assertEquals('apple/redirect', $redirectRoute->uri);
18+
$this->assertTrue(in_array('GET', $redirectRoute->methods));
19+
}
20+
21+
public function testAppleCallbackRouteIsRegistered(): void
22+
{
23+
$routes = $this->app['router']->getRoutes();
24+
25+
$callbackRoute = $routes->getByName('apple.callback');
26+
27+
$this->assertNotNull($callbackRoute);
28+
$this->assertEquals('apple/callback', $callbackRoute->uri);
29+
$this->assertTrue(in_array('POST', $callbackRoute->methods));
30+
}
31+
32+
public function testRedirectRouteUsesAppleSignInController(): void
33+
{
34+
$routes = $this->app['router']->getRoutes();
35+
$route = $routes->getByName('apple.redirect');
36+
37+
$controller = $route->getAction('controller');
38+
$this->assertStringContainsString('AppleSignInController', $controller);
39+
$this->assertStringContainsString('redirect', $controller);
40+
}
41+
42+
public function testCallbackRouteUsesAppleSignInController(): void
43+
{
44+
$routes = $this->app['router']->getRoutes();
45+
$route = $routes->getByName('apple.callback');
46+
47+
$controller = $route->getAction('controller');
48+
$this->assertStringContainsString('AppleSignInController', $controller);
49+
$this->assertStringContainsString('callback', $controller);
50+
}
51+
52+
public function testRoutesAreProtectedWithWebMiddleware(): void
53+
{
54+
$routes = $this->app['router']->getRoutes();
55+
56+
$redirectRoute = $routes->getByName('apple.redirect');
57+
$callbackRoute = $routes->getByName('apple.callback');
58+
59+
$this->assertTrue(in_array('web', $redirectRoute->middleware()));
60+
$this->assertTrue(in_array('web', $callbackRoute->middleware()));
61+
}
62+
63+
public function testRedirectRoutePathCanBeCustomized(): void
64+
{
65+
// Config shows customization is possible
66+
$this->assertEquals(
67+
'apple/redirect',
68+
config('services.sign_in_with_apple.routes.redirect_route')
69+
);
70+
}
71+
72+
public function testCallbackRoutePathCanBeCustomized(): void
73+
{
74+
$this->assertEquals(
75+
'apple/callback',
76+
config('services.sign_in_with_apple.routes.callback_route')
77+
);
78+
}
79+
}

0 commit comments

Comments
 (0)