diff --git a/src/Http/Requests/AuthKitLoginRequest.php b/src/Http/Requests/AuthKitLoginRequest.php index e485b01..49089e9 100644 --- a/src/Http/Requests/AuthKitLoginRequest.php +++ b/src/Http/Requests/AuthKitLoginRequest.php @@ -14,8 +14,14 @@ class AuthKitLoginRequest extends FormRequest { /** * Redirect the user to WorkOS for authentication. + * + * @param array{ + * screenHint?: 'sign-in'|'sign-up', + * domainHint?: string, + * loginHint?: string + * } $options */ - public function redirect(): Response + public function redirect(array $options = []): Response { WorkOS::configure(); @@ -26,6 +32,9 @@ public function redirect(): Response 'previous_url' => base64_encode(URL::previous()), ], 'authkit', + domainHint: $options['domainHint'] ?? null, + loginHint: $options['loginHint'] ?? null, + screenHint: $options['screenHint'] ?? null, ); $this->session()->put('state', json_encode($state)); diff --git a/tests/Feature/AuthKitLoginRequestTest.php b/tests/Feature/AuthKitLoginRequestTest.php new file mode 100644 index 0000000..d7ba94c --- /dev/null +++ b/tests/Feature/AuthKitLoginRequestTest.php @@ -0,0 +1,118 @@ +request = AuthKitLoginRequest::create('/', 'GET'); + $this->request->setLaravelSession(app('session.store')); +}); + +it('redirects to WorkOS without screen hint', function () { + $response = $this->request->redirect(); + + expect($response)->toBeInstanceOf(RedirectResponse::class); + + expect($response->headers->get('Location'))->toContain('https://api.workos.com/user_management/authorize') + ->toContain('client_id=test_client_id') + ->toContain('response_type=code') + ->toContain('redirect_uri='.urlencode('https://laravel.com/authenticate')) + ->toContain('provider=authkit') + ->not->toContain('screen_hint'); +}); + +it('redirects to WorkOS with sign-in screen hint', function () { + $response = $this->request->redirect(['screenHint' => 'sign-in']); + + expect($response)->toBeInstanceOf(RedirectResponse::class); + + expect($response->headers->get('Location')) + ->toContain('https://api.workos.com/user_management/authorize') + ->toContain('screen_hint=sign-in'); +}); + +it('redirects to WorkOS with sign-up screen hint', function () { + $response = $this->request->redirect(['screenHint' => 'sign-up']); + + expect($response)->toBeInstanceOf(RedirectResponse::class); + + expect($response->headers->get('Location')) + ->toContain('https://api.workos.com/user_management/authorize') + ->toContain('screen_hint=sign-up'); +}); + +it('stores state in session', function () { + $response = $this->request->redirect(); + + $sessionState = Session::get('state'); + expect($sessionState)->not->toBeNull(); + + $decodedState = json_decode($sessionState, true); + + expect($decodedState) + ->toHaveKey('state') + ->toHaveKey('previous_url') + ->and($decodedState['state'])->toHaveLength(20); +}); + +it('includes state in the authorization URL', function () { + $response = $this->request->redirect(); + + $location = $response->headers->get('Location'); + expect($location)->toContain('state='); + + parse_str(parse_url($location, PHP_URL_QUERY), $queryParams); + + expect($queryParams)->toHaveKey('state'); + + $sessionState = json_decode(Session::get('state'), true); + $urlState = json_decode($queryParams['state'], true); + + expect($urlState)->toBe($sessionState); +}); + +it('passes all parameters correctly to getAuthorizationUrl', function () { + $response = $this->request->redirect(['screenHint' => 'sign-up']); + + expect($response->headers->get('Location'))->not->toBeNull() + ->toBeString() + ->toContain('https://api.workos.com/user_management/authorize') + ->toContain('client_id=test_client_id') + ->toContain('response_type=code') + ->toContain('redirect_uri='.urlencode('https://laravel.com/authenticate')) + ->toContain('provider=authkit') + ->toContain('screen_hint=sign-up') + ->toContain('state='); +}); + +it('supports domain hint parameter', function () { + $response = $this->request->redirect(['domainHint' => 'laravel.com']); + + expect($response->headers->get('Location')) + ->toContain('domain_hint=laravel.com'); +}); + +it('supports login hint parameter', function () { + $response = $this->request->redirect(['loginHint' => 'francisco@laravel.com']); + + expect($response->headers->get('Location')) + ->toContain('login_hint='.urlencode('francisco@laravel.com')); +}); + +it('supports multiple parameters at once', function () { + $response = $this->request->redirect([ + 'screenHint' => 'sign-in', + 'domainHint' => 'laravel.com', + 'loginHint' => 'francisco@laravel.com', + ]); + + expect($response->headers->get('Location'))->toContain('screen_hint=sign-in') + ->toContain('domain_hint=laravel.com') + ->toContain('login_hint='.urlencode('francisco@laravel.com')); +});