Search by

hytale-community / hytale-auth-php

Grimille

A framework-agnostic PHP library for Sign in with Hytale using OpenID Connect and PKCE.

Package info

github.com/Hytale-Community/hytale-auth-php

Homepage

Issues

pkg:composer/hytale-community/hytale-auth-php

Statistics

Installs: 5

Dependents: 1

Suggesters: 0

Stars: 0

v0.1.0 2026-09-14 16:16 UTC

This package is not auto-updated.

Last update: 2026-09-14 22:48:01 UTC


README

Framework-agnostic PHP library for Sign in with Hytale using OpenID Connect, Authorization Code flow and PKCE.

The package provides the core authentication flow without depending on Laravel, Symfony or another framework. It uses PSR HTTP interfaces so the HTTP implementation remains up to the consuming application.

Package: hytale-community/hytale-auth-php

Features

  • OpenID Connect Authorization Code flow
  • PKCE with S256
  • Public and confidential OAuth clients
  • state and nonce generation and validation
  • Hytale OpenID discovery
  • RS256 ID token validation using Hytale JWKS
  • Validation of iss, aud, exp and nonce
  • Typed ID token claims
  • UserInfo support
  • Refresh token rotation support
  • Token revocation
  • Framework-agnostic PSR-18 / PSR-17 architecture

Requirements

  • PHP 8.2+
  • A PSR-18 HTTP client implementation
  • PSR-17 request and stream factories
  • A Hytale third-party application

Installation

composer require hytale-community/hytale-auth-php

The core package depends on PSR interfaces only. Your application must provide compatible HTTP implementations.

For example, with Guzzle:

composer require guzzlehttp/guzzle

Hytale endpoints

By default, the library uses the official Hytale OpenID Connect issuer:

https://connect.accounts.hytale.com

The library retrieves and validates Hytale's provider metadata through:

https://connect.accounts.hytale.com/.well-known/openid-configuration

UserInfo and JWKS URLs are read from that metadata. Authorization, token and revocation requests use Hytale's standard issuer paths documented above.

Configuration

use HytaleCommunity\HytaleAuth\Configuration;

$configuration = new Configuration(
    clientId: 'your-client-id',
    redirectUri: 'https://example.com/auth/hytale/callback',
);

For a confidential client, provide the client secret:

$configuration = new Configuration(
    clientId: 'your-client-id',
    redirectUri: 'https://example.com/auth/hytale/callback',
    clientSecret: 'your-client-secret',
);

Confidential clients authenticate against the token endpoint using HTTP Basic authentication. The client secret is never sent in the form body.

Creating the client

The package accepts PSR-compatible HTTP dependencies.

Using Guzzle:

use GuzzleHttp\Client;
use GuzzleHttp\Psr7\HttpFactory;
use HytaleCommunity\HytaleAuth\HytaleClient;

$httpClient = new Client();
$httpFactory = new HttpFactory();

$hytale = new HytaleClient(
    configuration: $configuration,
    httpClient: $httpClient,
    requestFactory: $httpFactory,
    streamFactory: $httpFactory,
);

Starting an authentication flow

use HytaleCommunity\HytaleAuth\Scope;

$authorization = $hytale->createAuthorizationRequest([
    Scope::Profile,
    Scope::GameOwnership,
]);

openid is automatically included when it is missing.

Before redirecting the user, persist these values in your session or another temporary server-side store:

$authorization->state;
$authorization->nonce;
$authorization->codeVerifier;

Then redirect the user to:

$authorization->url;

Available scopes

Enum Hytale scope
Scope::OpenId openid
Scope::Profile hytale:profile
Scope::SharedSource account:shared_source
Scope::GameOwnership account:game_ownership
Scope::ParentalManaged account:parental_managed
Scope::Offline offline

Use Scope::Offline when your Hytale application is allowed to receive refresh tokens.

Handling the callback

Pass the callback query parameters and the values stored before the redirect:

$result = $hytale->authenticate(
    parameters: $_GET,
    expectedState: $_SESSION['hytale_state'],
    codeVerifier: $_SESSION['hytale_code_verifier'],
    expectedNonce: $_SESSION['hytale_nonce'],
);

The library will:

  1. Handle OAuth errors returned by Hytale.
  2. Validate the callback state.
  3. Exchange the authorization code using PKCE.
  4. Discover Hytale's OpenID configuration.
  5. Retrieve Hytale's JWKS.
  6. Validate the ID token signature and claims.
  7. Return the validated tokens and claims.

Authentication result

Validated identity claims are available through:

$result->claims->subject;
$result->claims->profileUuid;
$result->claims->profileUsername;
$result->claims->sharedSource;
$result->claims->gameOwnership;
$result->claims->parentalManaged;

Tokens are available through:

$result->tokens->accessToken;
$result->tokens->idToken;
$result->tokens->expiresIn;
$result->tokens->refreshToken;
$result->tokens->tokenType;

Subject vs profile UUID

The OIDC sub claim is the stable user identifier for your Hytale application:

$result->claims->subject;

It should normally be used as the primary external account identifier in your application. The value is application-specific, so the same Hytale account can have a different sub in another third-party application.

A Hytale profile UUID is a separate public profile identity:

$result->claims->profileUuid;

When hytale:profile is requested, the user selects a Hytale profile during authentication. The profile UUID represents that selected public profile rather than the application-specific account identifier.

UserInfo

You can retrieve the current claims associated with an access token:

$userInfo = $hytale->userInfo(
    $result->tokens->accessToken,
);

Then access:

$userInfo->subject;
$userInfo->profileUuid;
$userInfo->profileUsername;
$userInfo->sharedSource;
$userInfo->gameOwnership;
$userInfo->parentalManaged;

Refresh tokens

If refresh tokens are enabled for your Hytale application and the offline scope was requested:

$newTokens = $hytale->refresh($storedRefreshToken);

Hytale refresh tokens rotate. When a refresh succeeds, replace the stored refresh token with the new one returned by Hytale:

$storedRefreshToken = $newTokens->refreshToken;

Do not reuse the old refresh token after a successful refresh. Reusing an old rotated token may invalidate the refresh token chain.

Revoking a token

Revoke a token when disconnecting a Hytale account or invalidating an authenticated session:

$hytale->revoke($refreshToken);

Error handling

OAuth errors returned by Hytale are exposed through OAuthException:

use HytaleCommunity\HytaleAuth\Exception\OAuthException;

try {
    $result = $hytale->authenticate(
        parameters: $_GET,
        expectedState: $state,
        codeVerifier: $codeVerifier,
        expectedNonce: $nonce,
    );
} catch (OAuthException $exception) {
    $exception->error;
    $exception->errorDescription;
}

Hytale may return OAuth errors such as:

access_denied
invalid_scope
invalid_request
invalid_grant
invalid_client
unauthorized_client

Validation failures such as an invalid state, nonce, issuer, audience or malformed response are rejected by the library.

Malformed or incomplete JSON responses from Hytale are exposed through UnexpectedResponseException:

use HytaleCommunity\HytaleAuth\Exception\UnexpectedResponseException;

Security notes

Always store state, nonce and the PKCE code_verifier server-side between the authorization redirect and callback.

Never expose a confidential client secret to browser or frontend code.

Redirect URIs registered with Hytale must match exactly. localhost and 127.0.0.1 are different redirect URIs.

Access tokens are opaque. Do not parse them. Use the validated ID token claims or the UserInfo endpoint instead.

ID tokens are validated against Hytale's RS256 JWKS and checked for the expected issuer, audience, expiration and nonce.

Authorization codes are short-lived and single-use. Exchange them immediately and never attempt to reuse them.

Local development

A local redirect URI can use HTTP when using localhost or 127.0.0.1, provided that exact URI is registered in your Hytale application.

Example:

http://localhost:8000/auth/hytale/callback

When developing this package alongside another Composer project, you can use a path repository:

{
  "repositories": [
    {
      "type": "path",
      "url": "../hytale-auth-php",
      "options": {
        "symlink": true
      }
    }
  ]
}

Then require the local development version:

composer require hytale-community/hytale-auth-php:@dev

Testing

Install development dependencies and run:

composer install
composer lint
composer test

Apply the configured PHP CS Fixer rules with:

composer format

The test suite mocks Hytale's HTTP endpoints and covers PKCE, authorization callbacks, token exchange, refresh-token rotation, revocation, malformed responses, ID token validation, UserInfo and public/confidential client behavior without contacting the real Hytale authentication service.

Framework integrations

This package intentionally contains no framework-specific session, cache, routing or persistence code.

A dedicated Laravel integration can build on top of this package while keeping the PHP SDK framework-agnostic.

License

MIT