Skip to content

Commit

Permalink
Merge pull request #207 from devdot/add-login-with-session
Browse files Browse the repository at this point in the history
Feature: Login with Session Cookie
  • Loading branch information
DumbergerL authored Jul 31, 2024
2 parents 4251974 + e3642b1 commit d8bc6d2
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Get GroupTypeRoles ([PR197](https://github.com/5pm-HDH/churchtools-api/pull/197))
- PHP coding standard ([PR193](https://github.com/5pm-HDH/churchtools-api/pull/193))
- Added new property 'postsEnabled' to the group type model ([PR204](https://github.com/5pm-HDH/churchtools-api/pull/204))
- Login with Session Cookie ([PR207](https://github.com/5pm-HDH/churchtools-api/pull/207))

### Changed

Expand Down
20 changes: 19 additions & 1 deletion src/CTConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use CTApi\Models\Groups\Person\PersonRequest;
use CTApi\Utils\CTUtil;
use GuzzleHttp\Cookie\CookieJar;
use GuzzleHttp\Cookie\SetCookie;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\TransferStats;
use Kevinrob\GuzzleCache\CacheMiddleware;
Expand Down Expand Up @@ -133,6 +134,11 @@ public static function authWithLoginToken(string $loginToken): Auth
return AuthRequest::authWithLoginToken($loginToken);
}

public static function authWithSessionCookie(string $cookieString): Auth
{
return AuthRequest::authWithSessionCookie($cookieString);
}

/**
* Auth via undocumented ajax-API. Use <code>authWithLoginToken()</code> instead.
* @param string $userId
Expand All @@ -153,7 +159,19 @@ public static function getSessionCookie(): ?array
if (empty($cookieData)) {
return null;
}
return end($cookieData);
return array_pop($cookieData);
}

public static function getSessionCookieString(): ?string
{
$cookieData = self::getSessionCookie();
return $cookieData ? (string) (new SetCookie($cookieData)) : null;
}

public static function setSessionCookie(string $cookieString): void
{
$cookie = SetCookie::fromString($cookieString);
self::getConfig()->cookieJar->setCookie($cookie);
}

/**
Expand Down
6 changes: 6 additions & 0 deletions src/Models/Common/Auth/AuthRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ public static function authWithLoginToken(string $loginToken): Auth
return (new AuthRequestBuilder())->authWithLoginToken($loginToken);
}

public static function authWithSessionCookie(string $sessionCookie): Auth
{
CTLog::getLog()->info('AuthRequest: Authenticate CTConfig with Session');
return (new AuthRequestBuilder())->authWithSessionCookie($sessionCookie);
}

public static function authWithUserIdAndLoginToken(string $userId, string $loginToken): bool
{
CTLog::getLog()->info('AuthRequest: Authenticate CTConfig with UserId and Token.');
Expand Down
24 changes: 24 additions & 0 deletions src/Models/Common/Auth/AuthRequestBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use CTApi\Exceptions\CTRequestException;
use CTApi\Models\Groups\Person\Person;
use CTApi\Utils\CTResponseUtil;
use GuzzleHttp\Cookie\SetCookie;

class AuthRequestBuilder
{
Expand Down Expand Up @@ -71,6 +72,29 @@ public function authWithLoginToken(string $loginToken): Auth
throw new CTAuthException("Authentication was not successfull.");
}

public function authWithSessionCookie(string $cookieString): Auth
{
$client = CTClient::getClient();
$cookie = SetCookie::fromString($cookieString);

try {
$response = $client->get('/api/whoami', [
'headers' => [
'cookie' => $cookie->getName() . '=' . $cookie->getValue(),
],
]);
$data = CTResponseUtil::dataAsArray($response);
$person = Person::createModelFromData($data);
} catch (CTRequestException $exception) {
throw new CTAuthException("Authentication was not successfull: " . $exception->getMessage(), $exception->getCode(), $exception);
}

if ($person->getId() != null && $person->getId() != -1 && $person->getId() != "-1") {
return new Auth($person->getId(), false);
}
throw new CTAuthException("Authentication was not successfull.");
}

public function authWithUserIdAndLoginToken(string $userId, string $loginToken): bool
{
$client = CTClient::getClient();
Expand Down
34 changes: 34 additions & 0 deletions tests/Integration/Requests/AuthRequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,40 @@ public function testAuthWithEmailAndPassword(): void
$this->assertNotNull($cookie);
}

public function testAuthWithSessionCookie(): void
{
$auth = IntegrationTestData::get()->authenticateUser();
$userId = $auth->userId;
$this->assertNotNull($userId);

$cookie = CTConfig::getSessionCookieString();
$this->assertNotNull($cookie);

// clear config
CTConfig::clearCookies();

// verify that we are not logged in now
CTConfig::setApiUrl(IntegrationTestData::get()->getApiUrl());
$this->assertFalse(CTConfig::validateAuthentication());

// clear again
CTConfig::clearCookies();

// login using the cookie
$auth = CTConfig::authWithSessionCookie($cookie);
$this->assertEquals($userId, $auth->userId);
$this->assertTrue(CTConfig::validateAuthentication());

// confirm we are still logged in
$authValid = CTConfig::validateAuthentication();
$this->assertTrue($authValid);

// confirm the session cookie was updated (but not replaced)
$updatedCookie = CTConfig::getSessionCookieString();
$this->assertNotNull($updatedCookie);
$this->assertSame(explode(';', $cookie, 2)[0], explode(';', $updatedCookie, 2)[0]);
}

public function testAuthWithUserIdAndLoginToken()
{
$auth = IntegrationTestData::get()->authenticateUser();
Expand Down

0 comments on commit d8bc6d2

Please sign in to comment.