Skip to content

Commit

Permalink
Merge pull request #40 from tjveldhuizen/issue-39
Browse files Browse the repository at this point in the history
Allow league/oauth2-server to provide private key in memory instead of in a file.
  • Loading branch information
steverhoades authored Aug 26, 2021
2 parents 77d3139 + d008a49 commit b21afa7
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 23 deletions.
26 changes: 19 additions & 7 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ matrix:
- php: 7.1
env: LEAGUE_VERSION=7.0.* JWT_VERSION=3.4.*
- php: 7.1
env: LEAGUE_VERSION=8.0.* JWT_VERSION=3.4.*
env: LEAGUE_VERSION=">=8.0.0 <=8.3.1" JWT_VERSION=3.4.*
- php: 7.1
env: LEAGUE_VERSION=^8.3.2 JWT_VERSION=3.4.*

- php: 7.2
env: LEAGUE_VERSION=5.1.* JWT_VERSION=3.4.*
Expand All @@ -49,21 +51,31 @@ matrix:
- php: 7.2
env: LEAGUE_VERSION=7.0.* JWT_VERSION=3.4.*
- php: 7.2
env: LEAGUE_VERSION=8.0.* JWT_VERSION=3.4.*
env: LEAGUE_VERSION=">=8.0.0 <=8.3.1" JWT_VERSION=3.4.*
- php: 7.2
env: LEAGUE_VERSION=^8.3.2 JWT_VERSION=3.4.*

- php: 7.3
env: LEAGUE_VERSION=8.0.* JWT_VERSION=3.4.*
env: LEAGUE_VERSION=">=8.0.0 <=8.3.1" JWT_VERSION=3.4.*
- php: 7.3
env: LEAGUE_VERSION=^8.3.2 JWT_VERSION=3.4.*

- php: 7.4
env: LEAGUE_VERSION=^8.0 JWT_VERSION=^3.4
env: LEAGUE_VERSION=">=8.0.0 <=8.3.1" JWT_VERSION=3.4.*
- php: 7.4
env: LEAGUE_VERSION=^8.0 JWT_VERSION=^4.0
env: LEAGUE_VERSION=^8.3.2 JWT_VERSION=3.4.*
- php: 7.4
env: LEAGUE_VERSION=">=8.0.0 <=8.3.1" JWT_VERSION=^4.0
- php: 7.4
env: LEAGUE_VERSION=^8.3.2 JWT_VERSION=^4.0

- php: 8.0
env: LEAGUE_VERSION=^8.0 JWT_VERSION=^4.0
env: LEAGUE_VERSION=">=8.0.0 <=8.3.1" JWT_VERSION=^4.0
- php: 8.0
env: LEAGUE_VERSION=^8.3.2 JWT_VERSION=^4.0

before_install:
- composer require league/oauth2-server:$LEAGUE_VERSION --prefer-source --no-update
- composer require league/oauth2-server:"$LEAGUE_VERSION" --prefer-source --no-update
- composer require lcobucci/jwt:$JWT_VERSION --prefer-source --no-update
- chmod 600 $TRAVIS_BUILD_DIR/tests/Stubs/private.key
- chmod 600 $TRAVIS_BUILD_DIR/tests/Stubs/public.key
Expand Down
15 changes: 11 additions & 4 deletions src/IdTokenResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/
namespace OpenIDConnectServer;

use Lcobucci\JWT\Signer\Key\InMemory;
use Lcobucci\JWT\Signer\Key\LocalFileReference;
use OpenIDConnectServer\Repositories\IdentityProviderInterface;
use OpenIDConnectServer\Entities\ClaimSetInterface;
Expand Down Expand Up @@ -89,10 +90,16 @@ protected function getExtraParams(AccessTokenEntityInterface $accessToken)
$builder = $builder->withClaim($claimName, $claimValue);
}

$token = $builder->getToken(
new Sha256(),
LocalFileReference::file($this->privateKey->getKeyPath(), (string) $this->privateKey->getPassPhrase())
);
if (
method_exists($this->privateKey, 'getKeyContents')
&& !empty($this->privateKey->getKeyContents())
) {
$key = InMemory::plainText($this->privateKey->getKeyContents());
} else {
$key = LocalFileReference::file($this->privateKey->getKeyPath(), (string)$this->privateKey->getPassPhrase());
}

$token = $builder->getToken(new Sha256(), $key);

return [
'id_token' => $token->toString()
Expand Down
64 changes: 52 additions & 12 deletions tests/ResponseTypes/IdTokenResponseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@

class IdTokenResponseTest extends TestCase
{
public function testGeneratesDefaultHttpResponse()
/**
* @dataProvider provideCryptKeys
*/
public function testGeneratesDefaultHttpResponse($privateKey)
{
$responseType = new IdTokenResponse(new IdentityProvider(), new ClaimExtractor());
$response = $this->processResponseType($responseType);
$response = $this->processResponseType($responseType, $privateKey);

self::assertInstanceOf(ResponseInterface::class, $response);
self::assertEquals(200, $response->getStatusCode());
Expand All @@ -35,10 +38,13 @@ public function testGeneratesDefaultHttpResponse()
self::assertObjectHasAttribute('refresh_token', $json);
}

public function testOpenIDConnectHttpResponse()
/**
* @dataProvider provideCryptKeys
*/
public function testOpenIDConnectHttpResponse($privateKey)
{
$responseType = new IdTokenResponse(new IdentityProvider(), new ClaimExtractor());
$response = $this->processResponseType($responseType, ['openid']);
$response = $this->processResponseType($responseType, $privateKey, ['openid']);

self::assertInstanceOf(ResponseInterface::class, $response);
self::assertEquals(200, $response->getStatusCode());
Expand All @@ -57,7 +63,10 @@ public function testOpenIDConnectHttpResponse()

// test additional claims
// test fails without claimsetinterface
public function testThrowsRuntimeExceptionWhenMissingClaimSetInterface()
/**
* @dataProvider provideCryptKeys
*/
public function testThrowsRuntimeExceptionWhenMissingClaimSetInterface($privateKey)
{
$this->expectException(\RuntimeException::class);

Expand All @@ -66,26 +75,32 @@ public function testThrowsRuntimeExceptionWhenMissingClaimSetInterface()
new IdentityProvider(IdentityProvider::NO_CLAIMSET),
new ClaimExtractor()
);
$this->processResponseType($responseType, ['openid']);
$this->processResponseType($responseType, $privateKey, ['openid']);
self::fail('Exception should have been thrown');
}

// test fails without identityinterface
public function testThrowsRuntimeExceptionWhenMissingIdentifierSetInterface()
/**
* @dataProvider provideCryptKeys
*/
public function testThrowsRuntimeExceptionWhenMissingIdentifierSetInterface($privateKey)
{
$this->expectException(\RuntimeException::class);
$responseType = new IdTokenResponse(
new IdentityProvider(IdentityProvider::NO_IDENTIFIER),
new ClaimExtractor()
);
$this->processResponseType($responseType, ['openid']);
$this->processResponseType($responseType, $privateKey, ['openid']);
self::fail('Exception should have been thrown');
}

public function testClaimsGetExtractedFromUserEntity()
/**
* @dataProvider provideCryptKeys
*/
public function testClaimsGetExtractedFromUserEntity($privateKey)
{
$responseType = new IdTokenResponse(new IdentityProvider(), new ClaimExtractor());
$response = $this->processResponseType($responseType, ['openid', 'email']);
$response = $this->processResponseType($responseType, $privateKey, ['openid', 'email']);

self::assertInstanceOf(ResponseInterface::class, $response);
self::assertEquals(200, $response->getStatusCode());
Expand All @@ -112,11 +127,36 @@ public function testClaimsGetExtractedFromUserEntity()
self::assertTrue($token->claims()->has("email"));
}

private function processResponseType($responseType, array $scopeNames = ['basic'])
public static function provideCryptKeys()
{
return array(
array(new CryptKey('file://'.__DIR__.'/../Stubs/private.key')),
array(new CryptKey(
<<<KEY
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDOBcFjGUlo3BJ9zjwQLgAHn6Oy5Si0uB7MublTiPob8rWTiCE4
weAFqzPoAB07vB0t0f8c1R8rmwHMD5ljWPBgJ8FewtwAUzprOBcau6DWukd/TKxX
WeVLAl/NZxijI+jR5QDBYLNBtj1G4LBVHMmINd3ryCycbf9ac3rcC8zhrQIDAQAB
AoGADfOJ0wIlXHp6rhZHLvlOezWuSjEGfqZxP3/cMvH1rerTrPfs+AD5AKlFTJKl
aCQm/bFYy0ULZVKL3pu30Wh2bo1nh/wLuLSI9Nz3O8jqAP3z0i07SoRoQmb8fRnn
dwoDFqnk3uGqcOenheSqheIgl9vdW/3avhD6nkMKZGxPYwECQQDoSj/xHogEzMqB
1Z2E5H/exeE9GQ7+dGITRR2MSgo9WvcKdRhGaQ44dsnTmqiZWAfqAPJjTQIIA/Cn
YRRTeBbNAkEA4w0iEvCIygGQOAnWuvVzlh+pxIB+BTeGkbiBG7nkYYc9b6B/Tw1B
GWGRddBr/FIfPvy1X2ip/TBpH+9bHnE2YQJBAIbZw/EYhmIy+UUSW9WwSUNsoOu1
Rm0V53HEZ/jvaq5fxpa9j5AgoO7KlzROzp3m6wE/93cKV6mLkAO7ae9jAekCQQCf
B6DZIS6+RrAMACAt3SOzf8P6BYG/B7Ayusd7cw2ang4S9JiW9xKkw2kN2wj3t1F5
XalwBTAjTdgj7ROmU+ehAkEAkOyXKONGBoVfaixRHgBP6jIBSSPbB2Aosi0QAURX
6GOY7wOS1pCSntTOBQxV7wVjqFwYAR10MSxFSNfpJ7RkzA==
-----END RSA PRIVATE KEY-----
KEY
),
));
}

private function processResponseType($responseType, $privateKey, array $scopeNames = ['basic'])
{
$_SERVER['HTTP_HOST'] = 'https://localhost';

$privateKey = new CryptKey('file://' . __DIR__ . '/../Stubs/private.key');
$responseType->setPrivateKey($privateKey);

// league/oauth2-server 5.1.0 does not support this interface
Expand Down

0 comments on commit b21afa7

Please sign in to comment.