Skip to content

Commit

Permalink
Rework access token for v2.2.0 API
Browse files Browse the repository at this point in the history
  • Loading branch information
partydragen committed Mar 9, 2024
1 parent 57bec25 commit ee01af4
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 35 deletions.
56 changes: 56 additions & 0 deletions upload/modules/OAuth2/classes/AccessToken.php
@@ -0,0 +1,56 @@
<?php
/**
* AccessToken
*
* @package Modules\OAuth2
* @author Partydragen
* @version 2.2.0
* @license MIT
*/
class AccessToken {

private $_data;
private bool $_authorised = false;
private User $_user;

public function __construct(string $value, string $field = 'access_token') {
$token = DB::getInstance()->get('oauth2_tokens', [$field, $value]);
if ($token->count()) {
$this->_data = $token->first();

if (hash_equals($value, $this->_data->access_token)) {
$this->_authorised = true;
}
}
}

public function exists(): bool {
return (!empty($this->_data));
}

public function isAuthorised(): bool {
return $this->_authorised;
}

public function hasScope(string $scope): bool {
return true;
}

/**
* Get the NamelessMC User that belong to this access token.
*
* @return User NamelessMC User that belong to this access token
*/
public function user(): User {
return $this->_user ??= new User($this->data()->user_id);
}

/**
* Get the access token data.
*
* @return object Get the access token data.
*/
public function data(): object {
return $this->_data;
}
}
26 changes: 6 additions & 20 deletions upload/modules/OAuth2/classes/AccessTokenAuthEndpoint.php
Expand Up @@ -9,6 +9,8 @@
*/
class AccessTokenAuthEndpoint extends EndpointBase {

private AccessToken $_token;

/**
* Determine if the passed Access Token (in Authorization header) is valid.
*
Expand All @@ -23,32 +25,16 @@ final public function isAuthorised(Nameless2API $api): bool {
}

$exploded = explode(' ', trim($auth_header));

if (count($exploded) !== 2 ||
strcasecmp($exploded[0], 'Bearer') !== 0) {
$api->throwError(Nameless2API::ERROR_MISSING_API_KEY, 'Authorization header not in expected format');
}

$access_token = $exploded[1];

return $this->validateAccessToken($api, $access_token);
$this->_token = new AccessToken($exploded[1]);
return $this->_token->isAuthorised();
}

/**
* Validate provided Access Token to make sure it matches.
*
* @param Nameless2API $api Instance of API to use for database connection.
* @param string $access_token Access token to check.
* @return bool Whether it matches or not.
*/
private function validateAccessToken(Nameless2API $api, string $access_token): bool {
$token = DB::getInstance()->get('oauth2_tokens', ['access_token', $access_token]);
if (!$token->count()) {
return false;
}
$token = $token->first();

return hash_equals($access_token, $token->access_token);
public function customParams(): array {
return [$this->_token];
}

}
12 changes: 7 additions & 5 deletions upload/modules/OAuth2/includes/endpoints/OAuth2TokenEndpoint.php
Expand Up @@ -24,13 +24,15 @@ public function execute(Nameless2API $api): void {
$api->throwError('oauth2:invalid_credentials');
}

// Get tokens by code
$token = DB::getInstance()->get('oauth2_tokens', [['application_id', $application->data()->id], ['code', $output['code']]]);
if (!$token->count()) {
// Get token by code
$token = new AccessToken($output['code'], 'code');
if ($token->exists()) {
$api->throwError('oauth2:invalid_code');
}
$token = $token->first();

$api->returnArray(['access_token' => $token->access_token, 'refresh_token' => $token->refresh_token]);
$api->returnArray([
'access_token' => $token->data()->access_token,
'refresh_token' => $token->data()->refresh_token
]);
}
}
14 changes: 4 additions & 10 deletions upload/modules/OAuth2/includes/endpoints/OAuth2UserEndpoint.php
Expand Up @@ -8,19 +8,13 @@ public function __construct() {
$this->_method = 'GET';
}

public function execute(Nameless2API $api): void {
$auth_header = HttpUtils::getHeader('Authorization');
$exploded = explode(' ', trim($auth_header));

// Get data from access token
$access_token = DB::getInstance()->get('oauth2_tokens', ['access_token', $exploded[1]]);
if (!$access_token->count()) {
$api->throwError(OAuth2ApiErrors::ERROR_NOT_AUTHORIZED);
public function execute(Nameless2API $api, AccessToken $token): void {
if (!$token->hasScope('identity')) {
$api->throwError('oauth2:missing_scope');
}
$access_token = $access_token->first();

// Make sure user still exist
$user = new User($access_token->user_id);
$user = $token->user();
if (!$user->exists()) {
$api->throwError(Nameless2API::ERROR_CANNOT_FIND_USER);
}
Expand Down

0 comments on commit ee01af4

Please sign in to comment.