Implemented Refresh, Signout and Invalidate endpoints (#1)

* test validate method

* Implemented Refresh, Signout and Invalidate endpoints

* Fix refresh and signout requests

* revert composer.lock

* fix changelog
This commit is contained in:
valentin-pazushko 2019-05-07 11:08:09 +03:00 committed by ErickSkrauch
parent 24138f24b5
commit 77ef50bcad
3 changed files with 188 additions and 3 deletions

View File

@ -16,12 +16,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [Change Skin](https://wiki.vg/Mojang_API#Change_Skin) endpoint. - [Change Skin](https://wiki.vg/Mojang_API#Change_Skin) endpoint.
- [Reset Skin](https://wiki.vg/Mojang_API#Reset_Skin) endpoint. - [Reset Skin](https://wiki.vg/Mojang_API#Reset_Skin) endpoint.
- [Blocked Servers](https://wiki.vg/Mojang_API#Blocked_Servers) endpoint. - [Blocked Servers](https://wiki.vg/Mojang_API#Blocked_Servers) endpoint.
- [Refresh](https://wiki.vg/Authentication#Refresh) endpoint.
- [Signout](https://wiki.vg/Authentication#Signout) endpoint.
- [Invalidate](https://wiki.vg/Authentication#Invalidate) endpoint.
### Changed ### Changed
- The constructor no longer has arguments. - The constructor no longer has arguments.
### Fixed ### Fixed
- Change `static` to `self` in `\Ely\Mojang\Response\Properties\Factory` to allow its extending. - Change `static` to `self` in `\Ely\Mojang\Response\Properties\Factory` to allow its extending.
- Fix `validate` endpoint URL.
### Removed ### Removed
- `\Ely\Mojang\Api::create()` static method. Use constructor instead. - `\Ely\Mojang\Api::create()` static method. Use constructor instead.

View File

@ -304,6 +304,35 @@ class Api {
); );
} }
/**
* @param string $accessToken
* @param string $clientToken
*
* @return \Ely\Mojang\Response\AuthenticateResponse
*
* @throws \GuzzleHttp\Exception\GuzzleException
*
* @url https://wiki.vg/Authentication#Refresh
*/
public function refresh(string $accessToken, string $clientToken): Response\AuthenticateResponse {
$response = $this->getClient()->request('POST', 'https://authserver.mojang.com/refresh', [
'json' => [
'accessToken' => $accessToken,
'clientToken' => $clientToken,
'requestUser' => true,
],
]);
$body = $this->decode($response->getBody()->getContents());
return new Response\AuthenticateResponse(
$body['accessToken'],
$body['clientToken'],
[],
$body['selectedProfile'],
$body['user']
);
}
/** /**
* @param string $accessToken * @param string $accessToken
* *
@ -315,7 +344,7 @@ class Api {
*/ */
public function validate(string $accessToken): bool { public function validate(string $accessToken): bool {
try { try {
$response = $this->getClient()->request('POST', 'https://authserver.mojang.com/authenticate', [ $response = $this->getClient()->request('POST', 'https://authserver.mojang.com/validate', [
'json' => [ 'json' => [
'accessToken' => $accessToken, 'accessToken' => $accessToken,
], ],
@ -330,6 +359,51 @@ class Api {
return false; return false;
} }
/**
* @param string $accessToken
* @param string $clientToken
*
* @throws GuzzleException
*
* @url https://wiki.vg/Authentication#Invalidate
*/
public function invalidate(string $accessToken, string $clientToken): void {
$this->getClient()->request('POST', 'https://authserver.mojang.com/invalidate', [
'json' => [
'accessToken' => $accessToken,
'clientToken' => $clientToken,
],
]);
}
/**
* @param string $login
* @param string $password
*
* @return bool
*
* @throws GuzzleException
*
* @url https://wiki.vg/Authentication#Signout
*/
public function signout(string $login, string $password): bool {
try {
$response = $this->getClient()->request('POST', 'https://authserver.mojang.com/signout', [
'json' => [
'username' => $login,
'password' => $password,
],
]);
if ($response->getStatusCode() === 204) {
return true;
}
} catch (Exception\ForbiddenException $e) {
// Suppress exception and let it just exit below
}
return false;
}
/** /**
* @param string $accessToken * @param string $accessToken
* @param string $accountUuid * @param string $accountUuid

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Ely\Mojang\Test; namespace Ely\Mojang\Test;
use Ely\Mojang\Api; use Ely\Mojang\Api;
use Ely\Mojang\Exception\ForbiddenException;
use Ely\Mojang\Exception\NoContentException; use Ely\Mojang\Exception\NoContentException;
use Ely\Mojang\Middleware\ResponseConverterMiddleware; use Ely\Mojang\Middleware\ResponseConverterMiddleware;
use Ely\Mojang\Middleware\RetryMiddleware; use Ely\Mojang\Middleware\RetryMiddleware;
@ -410,14 +411,120 @@ class ApiTest extends TestCase {
$this->assertRegExp('/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i', $body['clientToken']); $this->assertRegExp('/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i', $body['clientToken']);
} }
public function testAuthenticateInvalid() {
$this->mockHandler->append(new Response(403));
$this->expectException(ForbiddenException::class);
$this->api->authenticate('MockUsername', 'some password');
}
public function testRefreshSuccessful() {
$this->mockHandler->append($this->createResponse(200, [
'accessToken' => 'new access token value',
'clientToken' => 'client token value',
'selectedProfile' => [
'id' => '86f6e3695b764412a29820cac1d4d0d6',
'name' => 'MockUsername',
],
'user' => [
'id' => '86f6e3695b764412a29820cac1d4d0d6',
'properties' => [
[
'name' => 'preferredLanguage',
'value' => 'en',
],
[
'name' => 'twitch_access_token',
'value' => 'twitch oauth token',
],
],
],
]));
$result = $this->api->refresh('access token value', 'client token value');
/** @var \Psr\Http\Message\RequestInterface $request */
$request = $this->history[0]['request'];
$this->assertSame('https://authserver.mojang.com/refresh', (string)$request->getUri());
$this->assertSame('new access token value', $result->getAccessToken());
$this->assertSame('client token value', $result->getClientToken());
$this->assertSame('86f6e3695b764412a29820cac1d4d0d6', $result->getSelectedProfile()->getId());
$this->assertSame('MockUsername', $result->getSelectedProfile()->getName());
$this->assertFalse($result->getSelectedProfile()->isLegacy());
$this->assertFalse($result->getSelectedProfile()->isDemo());
$this->assertSame('86f6e3695b764412a29820cac1d4d0d6', $result->getUser()->getId());
$this->assertSame('preferredLanguage', $result->getUser()->getProperties()[0]->getName());
$this->assertSame('en', $result->getUser()->getProperties()[0]->getValue());
$this->assertSame('twitch_access_token', $result->getUser()->getProperties()[1]->getName());
$this->assertSame('twitch oauth token', $result->getUser()->getProperties()[1]->getValue());
}
public function testRefreshInvalid() {
$this->mockHandler->append(new Response(403));
$this->expectException(ForbiddenException::class);
$this->api->refresh('access token value', 'client token value');
}
public function testValidateSuccessful() { public function testValidateSuccessful() {
$this->mockHandler->append(new Response(204)); $this->mockHandler->append(new Response(204));
$this->assertTrue($this->api->validate('mocked access token'));
$result = $this->api->validate('mocked access token');
/** @var \Psr\Http\Message\RequestInterface $request */
$request = $this->history[0]['request'];
$this->assertSame('https://authserver.mojang.com/validate', (string)$request->getUri());
$this->assertTrue($result);
} }
public function testValidateInvalid() { public function testValidateInvalid() {
$this->mockHandler->append(new Response(403)); $this->mockHandler->append(new Response(403));
$this->assertFalse($this->api->validate('mocked access token'));
$result = $this->api->validate('mocked access token');
/** @var \Psr\Http\Message\RequestInterface $request */
$request = $this->history[0]['request'];
$this->assertSame('https://authserver.mojang.com/validate', (string)$request->getUri());
$this->assertFalse($result);
}
public function testInvalidateSuccessful() {
$this->mockHandler->append(new Response(200));
$this->api->invalidate('mocked access token', 'mocked client token');
/** @var \Psr\Http\Message\RequestInterface $request */
$request = $this->history[0]['request'];
$params = json_decode($request->getBody()->getContents(), true);
$this->assertSame('https://authserver.mojang.com/invalidate', (string)$request->getUri());
$this->assertSame('mocked access token', $params['accessToken']);
$this->assertSame('mocked client token', $params['clientToken']);
}
public function testSignoutSuccessful() {
$this->mockHandler->append(new Response(204));
$result = $this->api->signout('MockUsername', 'some password');
/** @var \Psr\Http\Message\RequestInterface $request */
$request = $this->history[0]['request'];
$this->assertSame('https://authserver.mojang.com/signout', (string)$request->getUri());
$this->assertTrue($result);
}
public function testSignoutInvalid() {
$this->mockHandler->append(new Response(403));
$result = $this->api->signout('MockUsername', 'some password');
/** @var \Psr\Http\Message\RequestInterface $request */
$request = $this->history[0]['request'];
$this->assertSame('https://authserver.mojang.com/signout', (string)$request->getUri());
$this->assertFalse($result);
} }
public function testJoinServer() { public function testJoinServer() {