A powerful extension for the XAuth plugin that provides an OAuth 2.0-like authentication layer, allowing external web applications to securely access player data.
- OAuth 2.0 Flow: Implements a standard authorization code flow for secure authentication.
- Web Server Integration: Runs a built-in, configurable web server to handle API requests.
- Registered Clients: Securely manage which external applications can connect, with unique client IDs and secrets.
- Rate Limiting: Protects your server from abuse with configurable request limits per client.
- Extensible Scopes: Allows other plugins to register their own data scopes, making player data available via the API.
- Database Support: Supports SQLite and MySQL for storing authorization codes and tokens.
- XAuth: This plugin is an extension of XAuth and requires it to be installed and active.
- libAsyncHttp: The web server functionality is provided by this virion, which is bundled with the plugin.
- Download the latest stable version of XAuthConnect from Poggit CI.
- Place the
XAuthConnect.pharfile into theplugins/folder of your PocketMine-MP server. - Restart your server. The plugin will generate its configuration files.
The plugin generates a config.yml file in plugin_data/XAuthConnect/ upon first run.
server-port: The port the web server will listen on (e.g., 8080).code-timeout: How long (in seconds) an authorization code is valid.
enabled: (true/false) Master switch to enable or disable SSL/TLS.cert-path: The path to your SSL certificate file (e.g.,/path/to/your/fullchain.pem).key-path: The path to your private key file (e.g.,/path/to/your/privkey.pem).
This is where you define the applications that can connect to your server.
web-integration:
registered-clients:
forum:
client-id: "forum_client_123"
client-secret: "super_secret_key"
name: "Community Forum"
redirect-uris:
- "https://forum.example.com/auth/callback"
allowed-scopes:
- "profile:nickname"
- "profile:uuid"client-id: A unique identifier for your application.client-secret: A secret key known only to your application and the server.name: A display name for the application, shown on the login page.redirect-uris: A list of valid URLs where the user can be redirected after authorization.allowed-scopes: The data scopes this client is allowed to request.
issuer_url: The URL of your server, used as theissclaim in ID tokens (e.g.,https://auth.your-server.com).private_key_path: Path to the RSA private key file for signing ID tokens. If left empty, the key will be generated automatically atplugin_data/XAuthConnect/private.key.
XAuthConnect provides a set of HTTP endpoints to handle the authentication flow.
Returns the OIDC discovery document with metadata about the authorization server.
- On Success: Returns a JSON object with OIDC discovery metadata.
{ "issuer": "http://127.0.0.1:8080", "authorization_endpoint": "http://127.0.0.1:8080/xauth/authorize", "token_endpoint": "http://127.0.0.1:8080/xauth/token", "userinfo_endpoint": "http://127.0.0.1:8080/xauth/user", "jwks_uri": "http://127.0.0.1:8080/xauth/jwks", "revocation_endpoint": "http://127.0.0.1:8080/xauth/revoke", "introspection_endpoint": "http://127.0.0.1:8080/xauth/introspect", "scopes_supported": ["openid", "profile:nickname", "profile:uuid"], "response_types_supported": ["code"], "grant_types_supported": ["authorization_code", "refresh_token"], "subject_types_supported": ["public"], "id_token_signing_alg_values_supported": ["RS256"], "token_endpoint_auth_methods_supported": ["client_secret_post"] }
Returns the JSON Web Key Set (JWKS) containing the public key for verifying ID tokens and access tokens.
- On Success: Returns a JSON object with a
keysarray.{ "keys": [ { "kty": "RSA", "kid": "...", "n": "...", "e": "AQAB", "use": "sig" } ] }
Server-Sent Events (SSE) endpoint for the client to wait for the login result. The server streams a JSON event with the login result or a timeout notification.
- Query Parameters:
request_id(required): The request ID returned by the login endpoint.
Starts the authorization process. This endpoint renders an HTML login page for the user.
- Query Parameters:
client_id(required): The ID of the registered client.redirect_uri(required): The callback URL where the user will be sent after login.scope(required): A space-separated list of requested data scopes (e.g.,profile:nickname profile:uuid).code_challenge(required): A PKCE code challenge.code_challenge_method(required): The method used to derive the code challenge (S256 or plain).state(optional): An opaque value used to maintain state between the request and callback.nonce(required for OpenID Connect): A nonce value to associate a Client session with an ID Token.error(optional): An error code from a previous failed attempt.
Handles the form submission from the authorize page.
- Form Parameters:
client_id,redirect_uri,scope,state(from the authorize step).code_challenge(required): The code challenge from the authorize step.code_challenge_method(required): The code challenge method (S256 or plain).username(required): The player's username.password(required): The player's XAuth password.
- On Success: Redirects the user to the
/xauth/consentpage to confirm scope access.
Displays a consent page to the user, asking them to approve or deny the requested scopes.
- Query Parameters:
client_id(required): The ID of the registered client.redirect_uri(required): The callback URL where the user will be sent after authorization.scope(required): A space-separated list of requested data scopes.code(required): The authorization code received from the login step.state(optional): An opaque value used to maintain state between the request and callback.code_challenge(required): The code challenge from the authorize step.code_challenge_method(required): The code challenge method (S256 or plain).username(required): The username of the authenticated player.nonce(required for OpenID Connect): A nonce value to associate a Client session with an ID Token.
- On Approval (POST):
- Form Parameters: Same as query parameters, plus
consent_action(value:approve). - On Success: Redirects the user to the
redirect_uriwith a temporarycodeand the originalstate.
- Form Parameters: Same as query parameters, plus
- On Denial (POST):
- Form Parameters: Same as query parameters, plus
consent_action(value:deny). - On Success: Redirects the user to the
redirect_uriwith anaccess_deniederror.
- Form Parameters: Same as query parameters, plus
Exchanges an authorization code for an access token, or a refresh token for a new access token. This should be a server-to-server request.
- Form Parameters:
client_id(required): The client ID.client_secret(required): The client secret.grant_type(required): Eitherauthorization_codeorrefresh_token.code(required forauthorization_code): The authorization code received from the login step.code_verifier(required forauthorization_code): The PKCE code verifier.refresh_token(required forrefresh_token): The refresh token obtained previously.
- On Success: Returns a JSON object with the access token. If the
openidscope was granted,id_tokenis also included.{ "access_token": "your_long_lived_access_token", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "new_refresh_token", "id_token": "eyJhbGciOiJSUzI1NiIs..." }
Allows a client to query the active state of an access or refresh token.
- Form Parameters:
token(required): The access token or refresh token to introspect.token_type_hint(optional): Hint about the type of the token (access_tokenorrefresh_token).client_id(required): The client ID.client_secret(required): The client secret.
- On Success: Returns a JSON object indicating the token's active status and associated metadata.
If the token is inactive or invalid:
{ "active": true, "scope": "profile:nickname profile:uuid", "client_id": "forum_client_123", "username": "Steve", "exp": 1678886400 }{ "active": false }
Allows a client to revoke an access token or refresh token.
- Form Parameters:
token(required): The access token or refresh token to revoke.token_type_hint(optional): Hint about the type of the token (access_tokenorrefresh_token).client_id(required): The client ID.client_secret(required): The client secret.
- On Success: Returns an empty 200 OK response.
Fetches user data using a valid access token.
- Headers:
Authorization: Bearer <access_token>
- On Success: Returns a JSON object containing the user data for the scopes granted to the token.
{ "profile:nickname": "Steve", "profile:uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" }
XAuthConnect allows other plugins to provide custom data scopes.
-
Create a ScopeProvider: Your class must implement the
ChernegaSergiy\XAuthConnect\api\ScopeProviderinterface.// In your plugin: src/MyPlugin/EconomyScopeProvider.php namespace MyPlugin; use ChernegaSergiy\XAuthConnect\api\ScopeProvider; class EconomyScopeProvider implements ScopeProvider { public function getProvidedScopes(): array { return ["economy:balance", "economy:level"]; } public function retrieveScopeData(string $username, array $scopes): array { $data = []; // Your logic to get player data, e.g., from EconomyAPI $balance = 123.45; // placeholder $level = 5; // placeholder foreach ($scopes as $scope) { if ($scope === 'economy:balance') { $data['economy:balance'] = $balance; } if ($scope === 'economy:level') { $data['economy:level'] = $level; } } return $data; } }
-
Register your provider: In your plugin's
onEnable(), get theXAuthConnectinstance and register your provider.// In your plugin: src/MyPlugin/Main.php $xauthConnect = $this->getServer()->getPluginManager()->getPlugin("XAuthConnect"); if ($xauthConnect instanceof \ChernegaSergiy\XAuthConnect\Main) { $xauthConnect->registerScopeProvider(new EconomyScopeProvider()); $this->getLogger()->info("Registered custom economy scopes with XAuthConnect."); }
-
Update Client Configuration: Server administrators can now add your new scopes (
economy:balance,economy:level) to theallowed-scopeslist for any client inconfig.yml.
The HTML for the authorization login page (login.html) is copied from the plugin's internal resources to plugin_data/XAuthConnect/web/login.html on first run. You can customize the login page by editing this file in the plugin_data folder.
Customizing Static Assets (CSS, JS, Images):
The plugin's web server does serve static files from the plugin_data/XAuthConnect/web/static/ directory.
To include custom CSS, JavaScript, or images:
- Manually create a
static/subfolder insideplugin_data/XAuthConnect/web/. - Place your custom files (e.g.,
styles.css) inside thisstatic/folder. - Link to them in your
login.htmlusing the/xauth/assets/URL path.
For example, if you have plugin_data/XAuthConnect/web/static/styles.css, you can link to it in login.html like this:
<link rel="stylesheet" href="/xauth/assets/styles.css">The template uses several placeholders that are replaced by the plugin:
{{client_name}}: Displays thenameof the application the user is logging into.{{error_message}}: Shows an error message if a previous login attempt failed. This is an HTML block, often a Bootstrap alert.{{oauth_params}}: This is a crucial placeholder that injects hidden input fields (client_id,redirect_uri,scope,state) into the form, ensuring the OAuth 2.0 parameters are passed along correctly. This must be included inside your<form>tag.
Contributions are welcome and appreciated! Here's how you can contribute:
- Fork the project
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Please make sure to update tests as appropriate and adhere to the existing coding style.
This project is licensed under the CSSM Unlimited License v2 (CSSM-ULv2). Please note that this is a custom license. See the LICENSE file for details.