mirror of
https://github.com/elyby/docs.git
synced 2025-04-13 22:49:15 +05:30
en docs seems to be finished
This commit is contained in:
parent
aa2f5a343f
commit
9d700ec276
@ -0,0 +1,318 @@
|
||||
# Authentication for Minecraft {#minecraft}
|
||||
This article contains information on authentication in Minecraft launchers and servers via the Ely.by authorization service.
|
||||
|
||||
The authentication protocol is implemented as similar as possible to the [original Mojang authentication protocol](http://wiki.vg/Authentication), but this documentation describes all features specific to the Ely.by service.
|
||||
|
||||
## General Provisions {#definitions}
|
||||
* All requests must be sent to `https://authserver.ely.by`.
|
||||
* A successful response will have a `200` status code. Any other code indicates an error.
|
||||
* The server always responds with JSON data, except for system errors and legacy requests. Use this to display proper error messages.
|
||||
* Standard error response format:
|
||||
```json
|
||||
{
|
||||
"error": "Short error description",
|
||||
"errorMessage": "Detailed error message in English for user display."
|
||||
}
|
||||
```
|
||||
|
||||
### Expected Errors {#errors}
|
||||
Unlike the original protocol, Ely.by uses a simplified set of errors:
|
||||
|
||||
#### IllegalArgumentException
|
||||
**Cause**: Incomplete or incorrect request parameters.
|
||||
**Solution**: Verify the request against the documentation.
|
||||
|
||||
#### ForbiddenOperationException
|
||||
**Cause**: Invalid user input or developer-provided data.
|
||||
**Solution**: Prompt the user to correct their input.
|
||||
|
||||
#### Not Found {#not-found}
|
||||
Indicated by a `404` status response.
|
||||
|
||||
## Authentication in the Launcher {#launcher}
|
||||
This section describes obtaining an `accessToken` for the Minecraft client. Successful authentication returns a **JWT token** with the `minecraft_server_session` [scope](./oauth.md#available-scopes).
|
||||
|
||||
:::warning
|
||||
We recommend using the [OAuth 2.0 protocol](./oauth.md) with the `minecraft_server_session` scope for better security and user experience.
|
||||
:::
|
||||
|
||||
### User Authentication {#auth-authenticate}
|
||||
Direct authentication using username/email, password, and optional 2FA token.
|
||||
|
||||
> **POST /auth/authenticate**
|
||||
>
|
||||
> **Parameters**:
|
||||
> * **username** (*string*): User's nickname or email (preferred).
|
||||
> * **password** (*string*): Password or `password:token` combination for 2FA.
|
||||
> * **clientToken** (*string*): Unique launcher identifier.
|
||||
> * **requestUser** (*bool*): Include `user` field in response if `true`.
|
||||
|
||||
The Ely.by accounts system supports additional user security with two-factor authentication. The Mojang’s authentication protocol doesn’t provide the possibility to pass TOTP tokens. To solve this problem and maintain compatibility with Yggdrasil’s server implementation, we suggest passing the token in the password field as password:token.
|
||||
|
||||
Unfortunately, not all users are aware of this feature, so it would be better to explicitly request the user’s token and concatenate it in the code when receiving an error about the user’s account being protected by two-factor authentication.
|
||||
|
||||
The logic is as follows:
|
||||
1. If the account has 2FA enabled, a `401` error is returned:
|
||||
```json
|
||||
{
|
||||
"error": "ForbiddenOperationException",
|
||||
"errorMessage": "Account protected with two factor auth."
|
||||
}
|
||||
```
|
||||
2. Upon receiving this error, you should ask the user to enter a TOTP token, and then repeat the authentication request with the same credentials, adding a postfix to the password in the form `:token`, where token is the value entered by the user.
|
||||
If the user’s password was “password123” and the token was “123456”, the `password` field value will become “password123:123456” after concatenating.
|
||||
3. If as a result of these actions you get a response with `401` status and `errorMessage` “Invalid credentials. Invalid email or password.”, it will indicate that the token passed is incorrect and must be re-requested from the user.
|
||||
|
||||
If all data is passed correctly, you will receive the following response:
|
||||
```json
|
||||
{
|
||||
"accessToken": "long_access_token_string",
|
||||
"clientToken": "provided_client_token",
|
||||
"availableProfiles": [
|
||||
{
|
||||
"id": "user_uuid_without_dashes",
|
||||
"name": "current_username"
|
||||
}
|
||||
],
|
||||
"selectedProfile": {
|
||||
"id": "user_uuid_without_dashes",
|
||||
"name": "current_username"
|
||||
},
|
||||
"user": { /* Included if requestUser is set */
|
||||
"id": "user_uuid_without_dashes",
|
||||
"username": "current_username",
|
||||
"properties": [
|
||||
{
|
||||
"name": "preferredLanguage",
|
||||
"value": "ru"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Token Refresh {#auth-refresh}
|
||||
Renew a valid `accessToken` without requiring the user's password.
|
||||
|
||||
> **POST /auth/refresh**
|
||||
>
|
||||
> **Parameters**:
|
||||
> * **accessToken** (*string*): Current access token.
|
||||
> * **clientToken** (*string*): Client identifier.
|
||||
> * **requestUser** (*bool*): Include `user` field in response if `true`.
|
||||
|
||||
:::note
|
||||
The original protocol also passes the value of `selectedProfile`, but in Mojang’s implementation it doesn’t affect anything. Our authentication server implementation ignores this parameter and relies on `accessToken` and `clientToken` values.
|
||||
:::
|
||||
|
||||
If you receive any of the provided errors, you should re-request the user password and perform normal authentication.
|
||||
|
||||
Successful response:
|
||||
```json
|
||||
{
|
||||
"accessToken": "new_access_token_string",
|
||||
"clientToken": "provided_client_token",
|
||||
"selectedProfile": {
|
||||
"id": "user_uuid_without_dashes",
|
||||
"name": "current_username"
|
||||
},
|
||||
"user": { /* Included if requestUser=true */
|
||||
"id": "user_uuid_without_dashes",
|
||||
"username": "current_username",
|
||||
"properties": [
|
||||
{
|
||||
"name": "preferredLanguage",
|
||||
"value": "ru"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Token Validation {#auth-validate}
|
||||
This request allows you to check whether the specified accessToken is valid or not. This request does not update the token or its lifetime, but only makes sure that it is still valid.
|
||||
|
||||
> **POST /auth/validate**
|
||||
>
|
||||
> **Parameters**:
|
||||
> * **accessToken** (*string*): The access token received after authentication.
|
||||
|
||||
AA successful response will be an empty body. An error will result in a `400` or `401` status. Example of server response when sending an expired token:
|
||||
```json
|
||||
{
|
||||
"error": "ForbiddenOperationException",
|
||||
"errorMessage": "Token expired."
|
||||
}
|
||||
```
|
||||
|
||||
### Invalidate All User Tokens {#auth-signout}
|
||||
Invalidate all tokens issued to a user.
|
||||
|
||||
> **POST /auth/signout**
|
||||
>
|
||||
> **Parameters**:
|
||||
> * **username** (*string*): User's username or email (preferred).
|
||||
> * **password** (*string*): User's password.
|
||||
|
||||
A successful response will be an empty body. Refer to the `error` field in the response body.
|
||||
|
||||
### Invalidate Specific Token {#auth-invalidate}
|
||||
The request allows you to invalidate the **accessToken**. In case the passed token cannot be found in the token store, **no error will be generated** and you will receive a successful response.
|
||||
|
||||
> **POST /auth/invalidate**
|
||||
>
|
||||
> **Parameters**:
|
||||
> * **accessToken** (*string*): A unique key obtained after authentication.
|
||||
> * **clientToken** (*string*): The unique identifier of the client with respect to which the accessToken was received.
|
||||
|
||||
A successful response will be an empty body. Refer to the `error` field in the response body.
|
||||
|
||||
## Server Authentication {#server}
|
||||
These requests are executed directly by the client and server using internal code or the authlib library (since version 1.7.2). They are only relevant if you have already authorized and run the game with a valid accessToken. You only need to replace the paths inside the game/library with the paths below.
|
||||
|
||||
Since you cannot directly change anything in authlib or the game, the values passed and server responses are not given here. If necessary, you can find this information yourself on the internet.
|
||||
|
||||
### Via Authlib {#authlib}
|
||||
:::info
|
||||
This part of the documentation describes the requests executed via authlib in game version 1.7.2+. For older versions, see [the section below](#legacy).
|
||||
:::
|
||||
|
||||
All requests in this category are executed on the `/session` sublayer. Each request is preceded by the type of request to be sent.
|
||||
|
||||
> **POST /session/join**
|
||||
>
|
||||
> A request to this URL is sent by the client at the time of connection to the server that has online-mode=true.
|
||||
|
||||
> **GET /session/hasJoined**
|
||||
>
|
||||
> The request to this URL is sent by the server that has online-mode=true after the client tries to connect to it completes the join request. The textures will be signed with the Ely.by key.
|
||||
|
||||
:::tip
|
||||
The signature verification key can be obtained from the [skins system](./skins-system.md#signature-verification-key-request).
|
||||
:::danger
|
||||
In rare cases the `signature` property will have the value `Cg==`. If the signature field has such value, there is no need to verify it, because it will always be incorrect.
|
||||
:::
|
||||
|
||||
### For older versions {#legacy}
|
||||
:::info
|
||||
This part of the documentation describes requests sent by older versions of Minecraft where the Authlib library wasn’t used. These include all versions below 1.7.2.
|
||||
:::
|
||||
|
||||
All requests in this category are executed on the `/session/legacy` sublayer. Each request is preceded by the type of request to be sent.
|
||||
|
||||
The principle of processing these requests is the same as for **the authlib**, the only difference is in the input parameters and return values.
|
||||
|
||||
> **GET /session/legacy/join**
|
||||
>
|
||||
> A request to this URL is sent by the client at the time of connection to the server that has online-mode=true.
|
||||
|
||||
> **GET /session/legacy/hasJoined?user=**
|
||||
>
|
||||
> The request to this URL is sent by the server that has online-mode=true after the client trying to connect to it successfully completes the join request.
|
||||
|
||||
It is important not to forget the GET parameter ?user= at the end of both requests to get the following URLs: `http://minecraft.ely.by/session/legacy/hasJoined?user=`.
|
||||
|
||||
## Single Player {#singleplayer}
|
||||
In essence, a single-player game is a local server created for a single player. At least it has been so since version 1.6, in which the local server mechanism was introduced.
|
||||
|
||||
However, the following request is relevant only for Minecraft 1.7.6+, when Authlib started to be used for loading skins.
|
||||
|
||||
### Profile Request {#profile-request}
|
||||
> **GET /session/profile/\{uuid\}**
|
||||
>
|
||||
> A request to this URL is sent by the client in a single-player game on a local server (created through the game itself). The UUID of the user with whom the client was launched is passed to the URL, and the response is information about the player’s textures in the same format as the `hasJoined` request.
|
||||
|
||||
## Prebuilt Authlib Libraries {#premade-authlib}
|
||||
:::tip
|
||||
Ely.by supports the authlib-injector library. This is the simplest and most universal way to install the authentication system in the game and its servers. For details, see [the corresponding documentation section](./authlib-injector.md).
|
||||
:::
|
||||
|
||||
Since manual implementation has difficulties in finding sources, connecting dependencies and finally compiling the result, on the [download page of our skin system](https://ely.by/load) you can download pre-built libraries with all necessary modifications. Select the desired version from the drop-down list and follow the installation instructions on the same page below.
|
||||
|
||||
In earlier versions of the game, the skin system was inside the game client, so the libraries below only provide authentication:
|
||||
- Minecraft 1.7.5: [authlib 1.3.1](/authlib/authlib-1.3.1.jar)
|
||||
- Minecraft 1.7.2: [authlib 1.3](/authlib/authlib-1.3.jar)
|
||||
|
||||
To install, you need to replace the original library located at `<Minecraft installation directory>/libraries/com/mojang/authlib/`. Make sure that the versions of the already present and replacement files match.
|
||||
:::warning
|
||||
Many launchers and server startup scripts check the integrity of the game files at startup and may not allow such modification
|
||||
:::
|
||||
|
||||
### Installing Authlib on a server {#authlib-server}
|
||||
The server also uses **authlib** to perform player authentication, so the appropriate changes should be applied to it as well. Below are instructions on how to install **authlib** for different Minecraft server implementations.
|
||||
|
||||
### Vanilla Server {#authlib-server-vanilla}
|
||||
Use an archiver to open the server file `minecraft_server.VERSION.jar`. In the same way, open the archive with authlib for the corresponding server version. You will see two windows in front of you: one with the server files, the other with the authlib files. You need to “drag and drop” all files and folders from the authlib archive, **except for the META-INF** directory, and confirm the replacement.
|
||||
<figure>
|
||||

|
||||
<figcaption>Please note: you should “drag and drop” the content below the server folders (into the .class file area).</figcaption>
|
||||
</figure>
|
||||
After these steps, you can close both windows and set `online-mode=true` in the `server.properties` file.
|
||||
|
||||
### Bukkit/Spigot {#authlib-server-spigot}
|
||||
First perform the installation as described for the [original server](#authlib-server-vanilla). Then download the libraries [commons-io](https://repo1.maven.org/maven2/commons-io/commons-io/2.5/commons-io-2.5.jar) and [commons-lang3](https://repo1.maven.org/maven2/org/apache/commons/commons-lang3/3.5/commons-lang3-3.5.jar), and then move the contents of the downloaded archives into the server files in the same way as authlib
|
||||
|
||||
### Forge/Sponge {#authlib-server-forge}
|
||||
Before performing the installation, it is necessary to determine which file is to be modified:
|
||||
- **≥1.16**: Modify `libraries/net/minecraft/server/VERSION-DIGITS/server-VERSION-DIGITS-extra.jar`.
|
||||
- **1.13-1.15**: Modify `libraries/net/minecraft/server/VERSION/server-VERSION-extra.jar`.
|
||||
- **\≤1.12**: Modify `minecraft_server.VERSION.jar`.
|
||||
|
||||
When the required file is found, perform an authlib installation for it, similar to [original server](#authlib-server-vanilla).
|
||||
|
||||
### Paper (PaperSpigot) {#authlib-server-paper}
|
||||
Installation is done similarly to [Bukkit/Spigot](#authlib-server-spigot) into the `cache/patched-VERSION.jar` file. After making changes, the server must be started via the jar file from the cache directory, because otherwise Paper will restore the original state of the file:
|
||||
```bash
|
||||
# Before
|
||||
java -jar paper-ВЕРСИЯ-БИЛД.jar
|
||||
# After
|
||||
java -jar cache/patched-ВЕРСИЯ.jar
|
||||
```
|
||||
|
||||
### BungeeCord {#authlib-server-bungeecord}
|
||||
:::tip
|
||||
You can use the [authlib-injector](./authlib-injector.md) library to install the authentication system without modifying the server internals.
|
||||
:::
|
||||
|
||||
Although BungeeCord is a proxy server, it performs player authentication on its own. Unfortunately, BungeeCord does not rely on Authlib, but implements the authentication process by itself, so you will need to modify the compiled `.class` files to install the Ely.by authentication system.
|
||||
|
||||
Follow the instructions below to install:
|
||||
1. Download the InClassTranslator program (we don’t give direct links, but it’s easy to find).
|
||||
2. Use an archiver to open the `BungeeCord.jar` file.
|
||||
3. Go to the path `net/md_5/bungee/connection` and find there the file `InitialHandler.class` (without any $ symbols).
|
||||
4. Unpack this file. In the simplest case you can do it by simply “pulling” it out of the archiver window.
|
||||
5. Open the extracted file in the InClassTranslator program and replace the line `https://sessionserver.mojang.com/session/minecraft/hasJoined?username=` with `https://authserver.ely.by/session/hasJoined?username=` as shown in the figure below:
|
||||

|
||||
6. Save the changes and drag the modified file back into the server archive. Confirm the replacement.
|
||||

|
||||
|
||||
After performing these steps, you can specify the value `online_mode=true` in the BungeeCord configuration file (`config.yml`).
|
||||
|
||||
:::info
|
||||
We also recommend performing an Authlib installation on all servers behind BungeeCord. This may be necessary for plugins that use the Mojang API. Instructions for installing on proxied servers are given [above](#authlib-server).
|
||||
|
||||
All servers must have `online-mode=false` in their configuration (`server.properties`), since users are already authorized by BungeeCord.
|
||||
:::
|
||||
|
||||
## Installation on versions below 1.7.2 {#install-legacy}
|
||||
For older versions there are quite a large variety of different cases, and it is not possible to cover them in this documentation. The whole setup consists of replacing certain strings in certain classes via **InClassTranslator**.
|
||||
|
||||
There is a [great post](http://www.rubukkit.org/threads/spisok-klassov-i-klientov-dlja-mcp.25108/#post-303710) (warning: in Russian, use any translator!) on the RuBukkit forum, which contains all the necessary information on class names on different versions of Minecraft. There is no point in retyping it here, so just go to its page and find the right version
|
||||
|
||||
### Installation example {#install-legacy-example}
|
||||
Suppose you want to install authentication on a server with version **1.5.2**.
|
||||
|
||||
First you follow the link above, select the version you want (1.5.2) and see the list of classes:
|
||||
* `bdk.class` - path to `joinserver`
|
||||
* `jg.class` - path to `checkserver`
|
||||
|
||||
Then you have to take the .jar file of the client and open it with any archiver. After that you need to find the **bdk.class** file. For this purpose it is convenient to use search.
|
||||
Once you have found the file, you need to extract it from the archive - just drag and drop it from there to a convenient dirctory.
|
||||
Next, run **InClassTranslator** and open this class in it. On the left will be a list of lines found in the file, which you can change. You only need to change the line responsible for the request to connect to the server:
|
||||
|
||||

|
||||
After that, you need to put the modified .class back into the game’s .jar file.
|
||||
|
||||
You need to perform the same operation with the server, only replace the reference with `hasJoined`.
|
||||
|
||||
After these actions you need to enable `online-mode=true` in the settings and the server will allow only those players who will be authorized through Ely.by.
|
256
i18n/en/docusaurus-plugin-content-docs/current/oauth.md
Normal file
256
i18n/en/docusaurus-plugin-content-docs/current/oauth.md
Normal file
@ -0,0 +1,256 @@
|
||||
# Authorization via OAuth2 protocol
|
||||
On this page you’ll find how to implement OAuth2 authorization on your project through the Ely.by Accounts service. The implementation of this protocol will allow your users to authorize using their Ely.by account.
|
||||
|
||||
## Application registration {#app-registration}
|
||||
First you need to [create a new application](https://account.ely.by/dev/applications/new). Select **Website** as the application type. For the Redirect URI you can get away with just specifying the domain, but to increase security it’s advised to use the full redirect path. Here are examples of valid addresses:
|
||||
* `https://example.com`
|
||||
* `https://example.com/oauth/ely`
|
||||
* `https://example.com/oauth.php?provider=ely`
|
||||
|
||||
After a successful creation of an application, you’ll be taken to the page containing a list of all your applications. If you click on the name of an application you’ll see its `clientId` identifier and its `clientSecret` secret. They’ll become important in later steps.
|
||||
|
||||
## Authorization initiation {#auth-init}
|
||||
To initiate the authorization flow, you’ll have to redirect the user to the following URL:
|
||||
```url
|
||||
https://account.ely.by/oauth2/v1?client_id=<clientId>&redirect_uri=<redirectUri>&response_type=code&scope=<scopesList>
|
||||
```
|
||||
|
||||
After creating the link, place it in your template:
|
||||
```html
|
||||
<a href="<your_link>">Login using Ely.by</a>
|
||||
```
|
||||
After clicking on the URL a user will be redirected to our login page after which they’ll be redirected back to the address specified in the `redirect_uri` parameter.
|
||||
|
||||
Reverse redirection returns as `<redirect_uri>?code=<auth_code>&state=<state>` for a successful authorization and `<redirect_uri>?error=<error_identifier>&error_message=<error_description>` for a failed one.
|
||||
|
||||
Examples of successful and unsuccessful redirects:
|
||||
```url
|
||||
https://example.com/oauth/ely.php?code=dkpEEVtXBdIcgdQWak4SOPEpTJIvYa8KIq5cW9GJ&state=ajckasdcjasndckbsadc
|
||||
https://example.com/oauth/ely.php?error=access_denied&error_message=The+resource+owner+or+authorization+server+denied+the+request.
|
||||
```
|
||||
|
||||
### Valid query parameters {#auth-init-params}
|
||||
| **Parameter** | **Example value** | **Description** |
|
||||
|--------------------|-----------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| *clientId* | `ely` | **Required**. ClientId that was received during registration. |
|
||||
| *redirect_uri* | `http://site.com/oauth.php` | **Required**. Return-forwarding address, which matches the address specified during the application registration. приложения. |
|
||||
| *response_type* | `code` | **Required**. Response type. At the moment, only `code` is supported. |
|
||||
| *scope* | `account_info account_email` | **Required**. The list of permissions that you want to access, separated by spaces. See all available permissions in the [section below](#available-scopes). |
|
||||
| *state* | `isfvubuysdboinsbdfvit` | Randomly generated string. Used as a session identifier to increase security. Will be returned unchanged after authorization is completed. |
|
||||
| *description* | `यो अनुप्रयोग विवरण` | If your application is available in several languages, you can use this field to override the default description in accordance with user’s preferred language. |
|
||||
| *prompt* | `consent` или `select_account` | Forcibly display the request for permissions (`consent`) or forcibly request an account selection (`select_account`). |
|
||||
| *login_hint* | `erickskrauch` или `erickskrauch@ely.by` | If a user has several accounts, then specifying username or user email in this parameter will automatically select corresponding account. This is useful in a case of re-login after the token has expired. |
|
||||
|
||||
### List of available scopes {#available-scopes}
|
||||
|
||||
| **Scope** | **Description** |
|
||||
|------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **account_info** | Get user information. |
|
||||
| **account_email** | Response to a request for user information will also contain user’s E-mail address. |
|
||||
| **offline_access** | With an access_token you will also recieve a refresh_token. See more at [the corresponding section](#refresh-token). |
|
||||
| **minecraft_server_session** | It will be possible to use `access_token` as a session identifier for the Minecraft. |
|
||||
|
||||
## Exchange auth code for a access key {#access_key}
|
||||
After receiving an authorization code (`auth_code`), you’ll need to exchange it for an authorization key (`access_key`). To do this, you must perform a POST request to the URL:
|
||||
```url
|
||||
https://account.ely.by/api/oauth2/v1/token
|
||||
```
|
||||
And pass in following parameters:
|
||||
* **client_id**: ClientID that was received during registration.
|
||||
* **client_secret**: ClientSecret that was received during application registration.
|
||||
* **redirect_uri**: The exact URI that was used for user redirection.
|
||||
* **grant_type**: In this case, `authorization_code` should be used.
|
||||
* **code**: Authorization code received in GET params after successful redirect.
|
||||
|
||||
```php title="An example of the exchange in PHP"
|
||||
<?php
|
||||
// This variable stores your OAuth2 parameters.
|
||||
$oauthParams = [
|
||||
'client_id' => 'ely', // Your ClientId received during registration.
|
||||
'client_secret' => 'Pk4uCtZw5WVlSUpvteJuTZkVqHXZ6aNtTaLPXa7X', // Your ClientSecret received at registration.
|
||||
'redirect_uri' => 'http://someresource.by/oauth/some.php', // The address you expect to get the user back to (current url).
|
||||
'grant_type' => 'authorization_code',
|
||||
];
|
||||
|
||||
// If an error occurs, abort the script execution.
|
||||
if (isset($_GET['error'])) {
|
||||
echo $_GET['error_message'];
|
||||
return;
|
||||
}
|
||||
|
||||
// Execute the code below only if the authorization code is received.
|
||||
if (!is_null($_GET['code'])) {
|
||||
$oauthParams['code'] = $_GET['code'];
|
||||
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_URL, 'https://account.ely.by/api/oauth2/v1/token');
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($curl, CURLOPT_POST, true);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($oauthParams));
|
||||
$out = json_decode(curl_exec($curl), true);
|
||||
curl_close($curl);
|
||||
}
|
||||
```
|
||||
:::info[Notes to the code]
|
||||
First, we declare the `$oauthParams` variable which will store the values that we got after registering the application.
|
||||
Then we check if there was an error. In which case, we immediately stop the execution.
|
||||
Then we create a POST request to exchange the `code` for an `access_token`, passing all required fields in the process.
|
||||
Then we execute the request, get the answer and parse it from JSON into the associative array.
|
||||
:::
|
||||
|
||||
### Server response {#access_key_result}
|
||||
In case of a successful request, the response body will contain the result of exchanging the authorization code for an `access_token`. Data is a JSON document and can be easily interpreted by tools of a used programming language.
|
||||
The JSON document body will contain the following fields:
|
||||
```json
|
||||
{
|
||||
"access_token": "4qlktsEiwgspKEAotazem0APA99Ee7E6jNryVBrZ",
|
||||
"refresh_token": "m0APA99Ee7E6jNryVBrZ4qlktsEiwgspKEAotaze", // Presented only in case of a request with offline_access rights
|
||||
"token_type": "Bearer",
|
||||
"expires_in": 86400 // Number of seconds for which the token is issued
|
||||
}
|
||||
```
|
||||
At this process authorization procedure is over. The resulting `access_token` can be used to obtain user information and to interact with our API.
|
||||
|
||||
## Getting user information {#get-user-info}
|
||||
If the received token has the `account_info` scope, then you can request information about the user’s account. To do it, you have to send a request to the URL:
|
||||
```url
|
||||
https://account.ely.by/api/account/v1/info
|
||||
```
|
||||
To send `access_token`, the `Authorization` header is used with the value of `Bearer {access_token}`.
|
||||
|
||||
```php title="An example of getting user information in PHP"
|
||||
<?php
|
||||
$accessToken = 'some_access_token_value';
|
||||
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_URL, 'https://account.ely.by/api/account/v1/info');
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, [
|
||||
'Authorization: Bearer ' . $accessToken,
|
||||
]);
|
||||
$result = json_decode(curl_exec($curl), true);
|
||||
curl_close($curl);
|
||||
```
|
||||
In response, you will receive a JSON document with the following contents:
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"uuid": "ffc8fdc9-5824-509e-8a57-c99b940fb996",
|
||||
"username": "ErickSkrauch",
|
||||
"registeredAt": 1470566470,
|
||||
"profileLink": "http:\/\/ely.by\/u1",
|
||||
"preferredLanguage": "be",
|
||||
"email": "erickskrauch@ely.by"
|
||||
}
|
||||
```
|
||||
Note that the email field will only be present when the account_email scope has been requested.
|
||||
:::note
|
||||
In the future, the number of returned fields may increase, but existing ones will remain the same.
|
||||
:::
|
||||
|
||||
## Refreshing access token {#refresh-token}
|
||||
If you have requested the scope `offline_access` during authorization, then along with your `access_token` you’ll also get `refresh_token`. This token doesn’t expire and can be used to obtain a new access token when that one expires.
|
||||
|
||||
To perform a token update, you have to send a POST request to the same URL that was used for exchanging the auth code for an access token, but with the next parameters:
|
||||
|
||||
| **Parameter** | **Description** |
|
||||
|-----------------|-----------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `client_id` | ClientID that was received during registration. |
|
||||
| `client_secret` | ClientSecret that was received during application registration. |
|
||||
| `scope` | The same scopes that were obtained for the initial access token. An attempt to extend this list will cause an error. |
|
||||
| `refresh_token` | The token itself that was obtained along with the access token. |
|
||||
|
||||
```php title="Example of a token refreshing in PHP"
|
||||
<?php
|
||||
// refresh_token received at authorization completion
|
||||
$refreshToken = 'm0APA99Ee7E6jNryVBrZ4qlktsEiwgspKEAotaze';
|
||||
|
||||
$requestParams = [
|
||||
'client_id' => 'ely', // Your ClientId received during registration
|
||||
'client_secret' => 'Pk4uCtZw5WVlSUpvteJuTZkVqHXZ6aNtTaLPXa7X', // Your ClientSecret received at registration
|
||||
'scope' => 'account_info account_email',
|
||||
'refresh_token' => $refreshToken,
|
||||
'grant_type' => 'refresh_token',
|
||||
];
|
||||
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_URL, 'https://account.ely.by/api/oauth2/v1/token');
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($curl, CURLOPT_POST, true);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($requestParams));
|
||||
$result = json_decode(curl_exec($curl), true);
|
||||
curl_close($curl);
|
||||
```
|
||||
The answer will have exactly the same body as the result of [exchanging auto code for an access token](#access_key_result). The `refresh_token` field will be absent.
|
||||
|
||||
## Available libraries {#libraries}
|
||||
A simpler way is to use a ready-made library, to which you’ll only have to provide registration parameters. Listed below are libraries for various programming languages. You can extend this list by providing your own library.
|
||||
* **PHP**:
|
||||
* [Official] https://github.com/elyby/league-oauth2-provider
|
||||
* **Ruby**:
|
||||
* [Official] https://github.com/elyby/omniauth-ely
|
||||
|
||||
## Possible errors {#errors}
|
||||
Below are the typical errors that you may receive after transmitting incorrect data to the authorization server. If you encounter an error that is not described in this documentation, please report it via [feedback form](https://ely.by/site/contact).
|
||||
|
||||
### Errors during authorization initiation {#errors-init-auth}
|
||||
This section describes the errors displayed when a user is redirected from your site to our authorization initiation page.
|
||||
|
||||
```
|
||||
Invalid request ({parameter} required).
|
||||
```
|
||||
This error means that you did not pass all the required parameters. To solve this error just add the missing parameter.
|
||||
|
||||
```
|
||||
Invalid response type '{invalid_response_type_value}'.
|
||||
```
|
||||
This error indicates that you passed an unsupported type of response_type. Currently, the only supported value is `code`.
|
||||
|
||||
```
|
||||
Invalid scope '{invalid_scope}'.
|
||||
```
|
||||
The error indicates that an unknown `scope` was requested. Make sure you request [supported scopes](#available-scopes).
|
||||
|
||||
```
|
||||
Can not find application you are trying to authorize.
|
||||
```
|
||||
This error indicates that the passed parameters do not correspond to any of the registered applications. To solve the problem, fix your `client_id` and `redirect_uri` values.
|
||||
|
||||
### Errors when exchanging code for a key {#issue-token-errors}
|
||||
If an error occurs, instead of the expected response with the `200` status, you will receive a `40x` code and the following 2 fields:
|
||||
```json
|
||||
{
|
||||
"error": "invalid_request",
|
||||
"error_description": "The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed. Check the \"code\" parameter."
|
||||
}
|
||||
```
|
||||
The `error` field contains the system error identifier, and `error_description` describes the error in English language.
|
||||
|
||||
#### Possible error values
|
||||
* `invalid_request`: Not all the required request parameters were passed or the `code` value was not found in the issued codes database.
|
||||
* `unsupported_grant_type`: This error indicates that you tried to authorize using an unknown for our OAuth2 server Grant-type.
|
||||
* `invalid_client`: This error occurs when the trio of values `client_id`, `client_secret` and `redirect_uri` didn’t match with any of the registered applications.
|
||||
|
||||
### Errors when requesting user information {#errors-request-user}
|
||||
Response status `401` indicates that the `Authorization` header is not present in the request or its value formed incorrectly. The response body will be as follows:
|
||||
```json
|
||||
{
|
||||
"name": "Unauthorized",
|
||||
"status": 401,
|
||||
"message": "Your request was made with invalid credentials."
|
||||
}
|
||||
```
|
||||
|
||||
A response with the `403` status indicates that the token transferred in the `Authorization` header does not contain the `account_info` scope or it has expired. The response will be in the following format:
|
||||
```json
|
||||
{
|
||||
"name": "Forbidden",
|
||||
"status": 403,
|
||||
"message": "You are not allowed to perform this action."
|
||||
}
|
||||
```
|
||||
|
||||
### Errors while updating access token {#errors-renewing-token}
|
||||
When updating the access token you may encounter the same errors from [exchanging auth code for an access token](#issue-token-errors), as well as several new ones:
|
||||
* `invalid_request`: Not all the required request parameters were passed or the `refresh_token` value wasn’t found in the issued tokens database.
|
||||
* `invalid_scope`: The unsupported scope was listed or requested more scopes than the original token had.
|
147
i18n/en/docusaurus-plugin-content-docs/current/skins-system.md
Normal file
147
i18n/en/docusaurus-plugin-content-docs/current/skins-system.md
Normal file
@ -0,0 +1,147 @@
|
||||
# Skins system
|
||||
|
||||
On this page you’ll find information about available endpoints of Ely.by’s skins system service. You can use any of them as an secondary or primary source of skins for your project.
|
||||
|
||||
Ely.by’s skins system service provides [proxying of textures from Minecraft premium users](#textures-proxy), which means that using this service, your players will see both premium Minecraft users’ skins and Ely.by users’ skins.
|
||||
|
||||
We strive to comply with the official skins system and do not support ears and HD-skins. The system supports capes, but doesn’t allow players to wear them on their own.
|
||||
|
||||
If you have suggestions for improving the existing functionality, please [create a new Issue](https://github.com/elyby/chrly/issues/new) at the [Chrly project repository](https://github.com/elyby/chrly).
|
||||
|
||||
:::note
|
||||
You can find more detailed information about the implementation of the skins system server in the [Chrly project repository](https://github.com/elyby/chrly).
|
||||
:::
|
||||
|
||||
## Requests URLs {#url}
|
||||
The skins system is located at the `http://skinsystem.ely.by` domain.
|
||||
In all queries, the `nickname` param must be replaced by the player’s name. The value is case-insensitive.
|
||||
|
||||
### Skin request {#skin-request}
|
||||
> **GET /skins/\{nickname\}.png**
|
||||
|
||||
URL for downloading a skin texture. The `.png` extension can be omitted. If textures aren’t found, the server will return a `404` status response.
|
||||
|
||||
### Cloak request {#cape-request}
|
||||
> **GET /cloaks/\{nickname\}.png**
|
||||
|
||||
URL for downloading a cape texture. The `.png` extension can be omitted. If textures aren’t found, the server will return a `404` status response.
|
||||
|
||||
### Textures request
|
||||
> **GET /textures/\{nickname\}**
|
||||
|
||||
Via this URL you can get textures in the format specified in the `textures` field of JSON property with the same name in response to [request for signed textures](https://wiki.vg/Mojang_API#UUID_-.3E_Profile_.2B_Skin.2FCape):
|
||||
```json
|
||||
{
|
||||
"SKIN": {
|
||||
"url": "http://example.com/skin.png",
|
||||
"metadata": {
|
||||
"model": "slim"
|
||||
}
|
||||
},
|
||||
"CAPE": {
|
||||
"url": "http://example.com/cape.png"
|
||||
}
|
||||
}
|
||||
```
|
||||
Depending on the availability of textures for the player, fields `SKIN` or `CAPE` may be absent. Unless the skin model is `slim`, the `metadata` field will be omitted.
|
||||
|
||||
The server will return an empty response with `204` status, if textures aren’t found.
|
||||
|
||||
### Profile request
|
||||
> **GET /profile/\{nickname\}**
|
||||
|
||||
This endpoint is an analog of the [player profile query in the Mojang’s API](https://wiki.vg/Mojang_API#UUID_-.3E_Profile_.2B_Skin.2FCape), but instead of UUID user is queried by his nickname. Just like in the Mojang’s API, you can append `?unsigned=false` to the URL to get textures with a signature. The response will also include an additional property with `name` ely.
|
||||
|
||||
If the user has no textures, they’ll be requested through the Mojang’s API, but the Mojang’s signature will be discarded and textures will be re-signed using [our signature key](#signature-verification-key-request).
|
||||
```json
|
||||
{
|
||||
"id": "ffc8fdc95824509e8a57c99b940fb996",
|
||||
"name": "ErickSkrauch",
|
||||
"properties": [
|
||||
{
|
||||
"name": "textures",
|
||||
"signature": "eks3dLJWzod92dLfWH6Z8uc6l3+IvrZtTj3zjwnj0AdVt44ODKoL50N+RabYxf7zF3C7tlJwT1oAtydONrxXUarqUlpVeQzLlfsuqUKBLi0L+/Y9yQLG3AciNqzEWq3hYaOsJrsaJday/hQmKFnpXEFCThTMpSuZhoAZIiH4VG48NhP70U93ejyXF9b1nPYnXP6k7BVB8LYSzcjZfdqY88jQJbbvRzOyX14ZSD0Ma92jceLNKmkTVc2UfRLUNXtQKtVSFUzlAjCXPJW89IIOZTRqLg65qstWwBvn6VuikyUB5EIxM8vuCh7zTkrMOx1v2Q0xIj8YSFcbnBH2bo87SYOIe1bOK57ZEeUJqY6uSgMlWs7dI5D3nmhFptErm72hg55Axdo1xbG4mvnmLYF7SA4yMDSytPPL+kA+sw3pafnvU2IZo38gqJSDOOpkOpdhUoHx85fzRJL8AcLSJiFlCZDl4pSi3cVuKy/xY5ohT/fJ6GEqpbZp3gACymn47zzI42VSh6j1DQnx2wnhqalTv0kE3qpAFpK/htSboQkFCW/bULO3b+vgU87XPlReT7UtH4yGLtixgs5GC8AzBraN8vOMv8TZCX9ab6mBBjOoDJjXa8Tq637TC75GxRHlpAN2jRHYvyp2zJwjUrML3u4eD4osHW+VBfl8D2l3nLJuemQ=",
|
||||
"value": "eyJ0aW1lc3RhbXAiOjE2MTQ5MzczMjc0MzcsInByb2ZpbGVJZCI6ImZmYzhmZGM5NTgyNDUwOWU4YTU3Yzk5Yjk0MGZiOTk2IiwicHJvZmlsZU5hbWUiOiJFcmlja1NrcmF1Y2giLCJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly9lbHkuYnkvc3RvcmFnZS9za2lucy82OWM2NzQwZDI5OTNlNWQ2ZjZhN2ZjOTI0MjBlZmMyOS5wbmcifX19"
|
||||
},
|
||||
{
|
||||
"name": "ely",
|
||||
"value": "but why are you asking?"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
The server will return an empty response with `204` status if the nickname wasn’t found locally nor via the Mojang’s API.
|
||||
|
||||
### Public Key Request {#signature-verification-key-request}
|
||||
> **GET /signature-verification-key.der**
|
||||
|
||||
This endpoint returns a public key that can be used to verify a texture’s signature. The key is provided in `DER` format, so it can be used directly in the Authlib, without modifying the signature checking algorithm.
|
||||
|
||||
> **GET /signature-verification-key.pem**
|
||||
|
||||
The same endpoint as the previous one, except that it returns the key in `PEM` format.
|
||||
|
||||
### Signed Textures Request
|
||||
> **GET /textures/signed/\{nickname\}**
|
||||
|
||||
This request is used in our [server skins system plugin](https://ely.by/server-skins-system) to load textures with the original Mojang’s signature. The textures received this way can be transferred to an unmodified game client without any changes. The answer will also include additional property with `name` equal to **ely**.
|
||||
```json
|
||||
{
|
||||
"id": "ffc8fdc95824509e8a57c99b940fb996",
|
||||
"name": "ErickSkrauch",
|
||||
"properties": [
|
||||
{
|
||||
"name": "textures",
|
||||
"signature": "QH+1rlQJYk8tW+8WlSJnzxZZUL5RIkeOO33dq84cgNoxwCkzL95Zy5pbPMFhoiMXXablqXeqyNRZDQa+OewgDBSZxm0BmkNmwdTLzCPHgnlNYhwbO4sirg3hKjCZ82ORZ2q7VP2NQIwNvc3befiCakhDlMWUuhjxe7p/HKNtmKA7a/JjzmzwW7BWMv8b88ZaQaMaAc7puFQcu2E54G2Zk2kyv3T1Bm7bV4m7ymbL8McOmQc6Ph7C95/EyqIK1a5gRBUHPEFIEj0I06YKTHsCRFU1U/hJpk98xXHzHuULJobpajqYXuVJ8QEVgF8k8dn9VkS8BMbXcjzfbb6JJ36v7YIV6Rlt75wwTk2wr3C3P0ij55y0iXth1HjwcEKsg54n83d9w8yQbkUCiTpMbOqxTEOOS7G2O0ZDBJDXAKQ4n5qCiCXKZ4febv4+dWVQtgfZHnpGJUD3KdduDKslMePnECOXMjGSAOQou//yze2EkL2rBpJtAAiOtvBlm/aWnDZpij5cQk+pWmeHWZIf0LSSlsYRUWRDk/VKBvUTEAO9fqOxWqmSgQRUY2Ea56u0ZsBb4vEa1UY6mlJj3+PNZaWu5aP2E9Unh0DIawV96eW8eFQgenlNXHMmXd4aOra4sz2eeOnY53JnJP+eVE4cB1hlq8RA2mnwTtcy3lahzZonOWc=",
|
||||
"value": "eyJ0aW1lc3RhbXAiOjE0ODYzMzcyNTQ4NzIsInByb2ZpbGVJZCI6ImM0ZjFlNTZmNjFkMTQwYTc4YzMyOGQ5MTY2ZWVmOWU3IiwicHJvZmlsZU5hbWUiOiJXaHlZb3VSZWFkVGhpcyIsInRleHR1cmVzIjp7IlNLSU4iOnsidXJsIjoiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS83Mzk1NmE4ZTY0ZWU2ZDhlYzY1NmFkYmI0NDA0ZjhlYmZmMzQxMWIwY2I5MGIzMWNiNDc2ZWNiOTk2ZDNiOCJ9fX0="
|
||||
},
|
||||
{
|
||||
"name": "ely",
|
||||
"value": "but why are you asking?"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
By default textures proxying isn’t used for this query. To enable it, add an additional GET parameter `?proxy=true`.
|
||||
|
||||
The server will return an empty response with `204` status, if textures aren’t found.
|
||||
|
||||
### Additional parameters
|
||||
You can also pass a range of additional **GET** parameters while making any of the above requests. They will be used to analyze the usage of the service by different versions of the game.
|
||||
|
||||
* `version`: The version of the protocol by which skins will be requested. The current version is `2`, i.e. you need to specify `version=2`.
|
||||
* `minecraft_version`: The version of Minecraft that the request is made from.
|
||||
* `authlib_version`: The version of the Authlib used. This option is relevant for Minecraft versions 1.7.6+, where a separate library is used to load skins instead of in-game code.
|
||||
|
||||
Here is an example of a textures request with parameters described above:
|
||||
```url
|
||||
http://skinsystem.ely.by/textures/erickskrauch?version=2&minecraft_version=1.14.0&authlib_version=1.5.25
|
||||
```
|
||||
|
||||
### Additional URLs
|
||||
You can also perform a skin and cape request by passing the nickname through the GET parameter. This feature is used to pass analytical parameters of game versions up to 1.5.2, where the nickname is simply appended to the end of the line. To do this, the entire string is arranged in such a way that the last parameter is `name`, after appending a nickname to which you get a full request string for textures.
|
||||
|
||||
> **GET /skins?name=\{nickname\}.png**
|
||||
|
||||
See the [skin request](#skin-request).
|
||||
|
||||
> **GET /cloaks?name=\{nickname\}.png**
|
||||
|
||||
See the [cape request](#cape-request).
|
||||
|
||||
```url title="Examples of requests for textures with parameters from above"
|
||||
http://skinsystem.ely.by/skins?version=2&minecraft_version=1.5.2&name=erickskrauch.png
|
||||
http://skinsystem.ely.by/cloaks?version=2&minecraft_version=1.4.7&name=notch
|
||||
```
|
||||
|
||||
## Textures proxying {#textures-proxy}
|
||||
Ely.by’s skins system service obtains textures from the official skin system in a case where no information about textures for the requested username was found in the database. The request will also be proxied if a skin entry is found, but it’s default.
|
||||
|
||||
To improve the throughput of the proxying algorithm, information about textures is cached in 2 stages:
|
||||
* Player’s names and UUIDs matches are stored [for 30 days](https://help.minecraft.net/hc/en-us/articles/360034636712-Minecraft-Usernames#article-container:~:text=How%20often%20can%20I%20change%20my%20username%3F).
|
||||
* Information about textures isn’t updated more often than [once a minute](https://wiki.vg/Mojang_API#UUID_-.3E_Profile_.2B_Skin.2FCape:~:text=You%20can%20request%20the%20same%20profile%20once%20per%20minute).
|
||||
|
||||
If you own a Minecraft premium account, but your nickname is busy, please contact our [support team](https://ely.by/site/contact) and after a short check we’ll pass the nickname on to you.
|
||||
|
||||
## Ready-made implementations
|
||||
Ready-made patch implementations and installation instructions can be found at the [download section of the main Ely.by website](https://ely.by/load).
|
Loading…
x
Reference in New Issue
Block a user