Skip to content

Commit

Permalink
Merge pull request #4 from seatplus/develop
Browse files Browse the repository at this point in the history
    add badge
    fix authentication container
  • Loading branch information
herpaderpaldent authored Oct 1, 2021
2 parents 5fab891 + 29d8756 commit 5145138
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
branches: [ main, develop ]

jobs:
laravel:
run-tests:

runs-on: ubuntu-latest

Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
"mockery/mockery": "^1.4",
"nunomaduro/collision": "^5.3",
"pestphp/pest-plugin-laravel": "^1.1",
"mikey179/vfsstream": "^1"
"mikey179/vfsstream": "^1",
"ext-openssl": "*"
},
"autoload": {
"psr-4": {
Expand Down
11 changes: 7 additions & 4 deletions src/DataTransferObjects/EsiAuthentication.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,23 @@

namespace Seatplus\EsiClient\DataTransferObjects;

use Firebase\JWT\JWT;
use Spatie\DataTransferObject\DataTransferObject;

class EsiAuthentication extends DataTransferObject
{
public int $client_id;
public string $secret;
public ?int $client_id;
public ?string $secret;
public string $access_token;
public string $refresh_token;
public string $token_expires = '1970-01-01 00:00:00';

public function getScopes() : array
{
$jwt = json_decode($this->access_token);
$jwt_payload_base64_encoded = explode('.', $this->access_token)[1];

return $jwt->scp ?? [];
$jwt_payload = JWT::urlsafeB64Decode($jwt_payload_base64_encoded);

return data_get(json_decode($jwt_payload), 'scp', []);
}
}
26 changes: 23 additions & 3 deletions tests/Pest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/


use Firebase\JWT\JWT;
use PHPUnit\Framework\TestCase;

uses(TestCase::class)
Expand Down Expand Up @@ -60,15 +61,34 @@ function buildEsiAuthentication(array $params = [])
$factory_array = [
'client_id' => $faker->randomNumber,
'secret' => $faker->md5,
'access_token' => json_encode([
'access_token' => buildJWT(json_encode([
'scp' => [],
]),
])),
'refresh_token' => $faker->sha1,
];

foreach ($params as $key => $value) {
$factory_array[$key] = $value;
$factory_array[$key] = $key === 'access_token' ? buildJWT($value) : $value;
}

return new \Seatplus\EsiClient\DataTransferObjects\EsiAuthentication($factory_array);
}

function buildJWT(string $payload): string
{
$jwt_header = json_encode([
"alg" => "RS256",
"kid" => "JWT-Signature-Key",
"typ" => "JWT",
]);

$data = JWT::urlsafeB64Encode($jwt_header) . "." . JWT::urlsafeB64Encode($payload);

$signature = hash_hmac(
'sha256',
$data,
'test'
);

return "${data}.${signature}";
}
13 changes: 13 additions & 0 deletions tests/Unit/EsiAuthenticationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

it('is possible to create EsiAuthenticationContainer without esi id and secret', function () {
$authenticaton = new \Seatplus\EsiClient\DataTransferObjects\EsiAuthentication([
'access_token' => 'access_token',
'refresh_token' => 'access_token',
'token_expires' => 'now',
]);

expect($authenticaton)
->toBeInstanceOf(\Seatplus\EsiClient\DataTransferObjects\EsiAuthentication::class)
->token_expires->toBe('now');
});
42 changes: 30 additions & 12 deletions tests/Unit/Services/RefreshTokenServiceTest.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
<?php

use Firebase\JWT\JWT;
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;

/** @runInSeparateProcess */
it('updates access token with refresh token', function () {
$jwt_token = json_encode([

// create a private key for signing the JWT Token
$privKey = openssl_pkey_new(['digest_alg' => 'sha256',
'private_key_bits' => 1024,
'private_key_type' => OPENSSL_KEYTYPE_RSA, ]);

// define the payload
$payload = [
"scp" => [
"esi-skills.read_skills.v1",
"esi-skills.read_skillqueue.v1",
Expand All @@ -16,36 +25,45 @@
"azp" => "my3rdpartyclientid",
"name" => "Some Bloke",
"owner" => "8PmzCeTKb4VFUDrHLc/AeZXDSWM=",
"exp" => 1534412504,
"exp" => now()->addHour()->timestamp,
"iss" => "login.eveonline.com",
]);
];

// encode the jwt token
$jwt_token = JWT::encode($payload, $privKey, 'RS256');

// build the authentication container
$authentication = buildEsiAuthentication([
'access_token' => $jwt_token,
]);

// create the client mock and responses from said client
$mock = new \GuzzleHttp\Handler\MockHandler([
new Response(200, [], json_encode(['access_token' => 'bar'])),
new Response(200, [], json_encode(['access_token' => $jwt_token, 'foo' => 'bar'])),
new Response(200, [], json_encode(['jwks' => ['one', 'two', 'three']])),
]);

$client = new Client([
'handler' => HandlerStack::create($mock),
]);

// mock JWT
$jwt_mock = Mockery::mock('overload:' . \Firebase\JWT\JWT::class);
$jwt_mock->shouldReceive('decode')->once()->andReturn([
"iss" => "login.eveonline.com",
"exp" => now()->addHour()->timestamp,
]);
// get the public key which we need to decode the jwt token
$pubKey = openssl_pkey_get_details($privKey);
$pubKey = $pubKey['key'];

// mock the JWK static method and return the pub key
$jwk_mock = Mockery::mock('overload:' . \Firebase\JWT\JWK::class);
$jwk_mock->shouldReceive('parseKeySet')->once()->andReturn([]);
$jwk_mock->shouldReceive('parseKeySet')->once()->andReturn($pubKey);

// construct the service
$service = new \Seatplus\EsiClient\Services\RefreshToken($authentication, $client);

// use service to get the refresh Token
$response = $service->getRefreshTokenResponse();

expect($response)->toBe(['access_token' => 'bar']);
// assert the expected result. See the mocked response as reference
expect($response)
->toBeArray()
->toHaveKey('access_token', $jwt_token)
->toHaveKey('foo', 'bar');
});

0 comments on commit 5145138

Please sign in to comment.