Skip to content

Instantly share code, notes, and snippets.

@Aizistral
Last active February 14, 2024 05:33
Show Gist options
  • Save Aizistral/7046f09fc170b2a8c78cc0620f70ecfa to your computer and use it in GitHub Desktop.
Save Aizistral/7046f09fc170b2a8c78cc0620f70ecfa to your computer and use it in GitHub Desktop.
What can still be done with unmigrated Mojang accounts?

What can still be done with unmigrated Mojang accounts?

Date: 14.09.2022
Author: Aizistral
In collaboration with: LapisDemon, 0n#5210

It is already widely known that unmigrated accounts can no longer be used to log into official launcher, and there is almost nothing you can do with them on minecraft.net website, except migrate. However, some third-party launchers, such as PolyMC, still offer the option to log into the game from Mojang account, even though it is not possible to play multiplayer in such case. This raised the question in my mind: how much exactly can still be done with unmigrated account?

Precise data on this matter has proven hard to come by. Luckily - with the help of LapisDemon, who have kindly supplied one of her unmigrated accounts for testing, I was able to collect some myself. All data presented herein is published with her full permission.

This research sets the goal of answering the following questions:

  1. Can name and UUID of the account be established with accounts credentials (e-mail & password)?
  2. Can access tokens still be obtained for unmigrated account?
  3. If above is true, is it possible to verify validity of such tokens later?
  4. Can name and UUID of the account be established with access token alone?
  5. Is it possible to establish what skin and cape of the account are, and how?
  6. Is it indeed impossible to join multiplayer servers with unmigrated account?
  7. Is it possible to get banned while playing from unmigrated account?
  8. With full access, is it possible to change account's name, skin or cape?
  9. With full access, is it possible to change account's e-mail or password?
  10. Can trustless authentication schemes (key-based and skin-based) be used to verify unmigrated accounts?
  11. How can answers to the above change in future?

Login on minecraft.net

Upon logging into account on minecraft.net, we could observe the following page: image

The only other account-related page accessible was billing information page, which looked like this: image

Authentication

Here, we tried to use known API endpoints for legacy Mojang authentication. While official launcher no longer makes use of them, they are still relevant for authentication on minecraft.net.

  • Request Type: POST
  • Request Payload:
{
  "agent": {
    "name": "Minecraft",
    "version": 1
  },
  "username": "████████@█████████",
  "password": "██████████████████████",
  "requestUser": true
}
  • Response Code: 200 OK
  • Response Contents:
{
  "accessToken": "eyJhbGciOiJIUzI1NiJ9.eyJhZ2ciOiJBZHVsdCIsInN1YiI6IjI0N2ZhNjc4MTY3MTBiZWVkM2EzNzQzMDUwNGNlMTkwIiwibGltIjoibXNhZm9yY2VkIiwieWdndCI6ImU4OWUxNTIyNTdmMjQyNzA5NDNhNjAxYTIyNmQ5YWE5Iiwic3ByIjoiM2UyOGE3OTg3ZDZkNDBhMWI2ZjdhNDZkMzg1NzdkNjEiLCJpc3MiOiJZZ2dkcmFzaWwtQXV0aCIsImV4cCI6MTY2MzI1ODc3OCwiaWF0IjoxNjYzMDg1OTc4fQ.TeDSOySJMixikbTZzmI6umq76HvJVXFI0h8M58Tv5x4",
  "user": {
    "properties": [
      {
        "name": "preferredLanguage",
        "value": "de-de"
      },
      {
        "name": "registrationCountry",
        "value": "DE"
      }
    ],
    "id": "247fa67816710beed3a37430504ce190",
    "username": "████████@█████████"
  },
  "clientToken": "f249dec8198944c7ac0208fe4d9a9d19",
  "selectedProfile": {
    "name": "Iinda",
    "id": "3e28a7987d6d40a1b6f7a46d38577d61"
  },
  "availableProfiles": [
    {
      "name": "Iinda",
      "id": "3e28a7987d6d40a1b6f7a46d38577d61"
    }
  ]
}
  • Decoded Access Token Header:
{
  "alg": "HS256"
}
  • Decoded Access Token Payload:
{
  "agg": "Adult",
  "sub": "247fa67816710beed3a37430504ce190",
  "lim": "msaforced",
  "yggt": "e89e152257f24270943a601a226d9aa9",
  "spr": "3e28a7987d6d40a1b6f7a46d38577d61",
  "iss": "Yggdrasil-Auth",
  "exp": 1663258778,
  "iat": 1663085978
}
  • Note: Tokens used further are different, but they were all obtained through additional authenticate requests.
  • Request Type: POST
  • Request Payload:
{
  "accessToken": "eyJhbGciOiJIUzI1NiJ9.eyJhZ2ciOiJBZHVsdCIsInN1YiI6IjI0N2ZhNjc4MTY3MTBiZWVkM2EzNzQzMDUwNGNlMTkwIiwibGltIjoibXNhZm9yY2VkIiwieWdndCI6IjE1YmQ1ODA0ZGE3MDQ3YzlhYWEzNWQxM2Y4MDZkZTUwIiwic3ByIjoiM2UyOGE3OTg3ZDZkNDBhMWI2ZjdhNDZkMzg1NzdkNjEiLCJpc3MiOiJZZ2dkcmFzaWwtQXV0aCIsImV4cCI6MTY2MzI1OTE4NiwiaWF0IjoxNjYzMDg2Mzg2fQ.bIzembxx2eNwwkXw_HQXwpMVMlKow9ctLNiE5pvRq34"
}
  • Response Code: 204 OK
  • Response Contents: none
  • Request Type: POST
  • Request Payload:
{
  "accessToken": "eyJhbGciOiJIUzI1NiJ9.eyJhZ2ciOiJBZHVsdCIsInN1YiI6IjI0N2ZhNjc4MTY3MTBiZWVkM2EzNzQzMDUwNGNlMTkwIiwibGltIjoibXNhZm9yY2VkIiwieWdndCI6IjE1YmQ1ODA0ZGE3MDQ3YzlhYWEzNWQxM2Y4MDZkZTUwIiwic3ByIjoiM2UyOGE3OTg3ZDZkNDBhMWI2ZjdhNDZkMzg1NzdkNjEiLCJpc3MiOiJZZ2dkcmFzaWwtQXV0aCIsImV4cCI6MTY2MzI1OTE4NiwiaWF0IjoxNjYzMDg2Mzg2fQ.bIzembxx2eNwwkXw_HQXwpMVMlKow9ctLNiE5pvRq34",
  "clientToken": "cf1e3e54c892497c843e63cef0591f34",
  "requestUser": true
}
  • Response Code: 200 OK
  • Response Contents:
{
  "accessToken": "eyJhbGciOiJIUzI1NiJ9.eyJhZ2ciOiJBZHVsdCIsInN1YiI6IjI0N2ZhNjc4MTY3MTBiZWVkM2EzNzQzMDUwNGNlMTkwIiwibGltIjoibXNhZm9yY2VkIiwieWdndCI6IjU3OWE0NWZiZDg2NzQyMGU4NTE5NGM1YTUzOGJkM2EyIiwic3ByIjoiM2UyOGE3OTg3ZDZkNDBhMWI2ZjdhNDZkMzg1NzdkNjEiLCJpc3MiOiJZZ2dkcmFzaWwtQXV0aCIsImV4cCI6MTY2MzI1OTg1NSwiaWF0IjoxNjYzMDg3MDU1fQ.hKboEFh72EihcW2oVqpSyCohqOaROIWbpq7xOMsxOco",
  "user": {
    "properties": [
      {
        "name": "preferredLanguage",
        "value": "de-de"
      },
      {
        "name": "registrationCountry",
        "value": "DE"
      }
    ],
    "id": "247fa67816710beed3a37430504ce190",
    "username": "████████@█████████"
  },
  "clientToken": "cf1e3e54c892497c843e63cef0591f34",
  "selectedProfile": {
    "name": "Iinda",
    "id": "3e28a7987d6d40a1b6f7a46d38577d61"
  }
}
  • Request Type: POST
  • Request Payload:
{
  "accessToken": "eyJhbGciOiJIUzI1NiJ9.eyJhZ2ciOiJBZHVsdCIsInN1YiI6IjI0N2ZhNjc4MTY3MTBiZWVkM2EzNzQzMDUwNGNlMTkwIiwibGltIjoibXNhZm9yY2VkIiwieWdndCI6IjJjNmNiMDZlMWE5ODRhNDk4NWRiNzQwNTg0NzYwZTNlIiwic3ByIjoiM2UyOGE3OTg3ZDZkNDBhMWI2ZjdhNDZkMzg1NzdkNjEiLCJpc3MiOiJZZ2dkcmFzaWwtQXV0aCIsImV4cCI6MTY2MzI2MDQzMCwiaWF0IjoxNjYzMDg3NjMwfQ.eiuDGFu5n6fAE6xVMjgj5iJVZskKTvELBjWoL0bM1Po",
  "clientToken": "cf1e3e54c892497c843e63cef0591f34"
}
  • Response Code: 204 OK
  • Response Contents: none
  • Note: Further validate request for this token confirmed that it was indeed invalidated.
  • Request Type: POST
  • Request Payload:
{
  "username": "████████@█████████",
  "password": "██████████████████████"
}
  • Response Code: 204 OK
  • Response Contents: none
  • Note: Further validate request for one of the tokens issued beforehand confirmed that it was indeed invalidated.

Mojang API

Here we tried to perform some conventional requests against Mojang's API, to see what parts of it remain accessible for unmigrated accounts. Some of them do not require authorization and can therefore be performed by anyone for any account, others require access token.

  • Request Type: GET
  • Authorization: No
  • Response Code: 200 OK
  • Response Contents:
{
  "name": "Iinda",
  "id": "3e28a7987d6d40a1b6f7a46d38577d61"
}
  • Request Type: GET
  • Authorization: No
  • Response Code: 200 OK
  • Response Contents:
[
  {
    "name": "Iinda"
  }
]
  • Note: This request was performed on September 12, before name history endpoint was removed. As of September 13 services responded with 410 Gone, as for all other accounts; some time later this was changed to 404 Not Found.
  • Request Type: GET
  • Authorization: No
  • Response Code: 200 OK
  • Response Contents:
{
  "id": "3e28a7987d6d40a1b6f7a46d38577d61",
  "name": "Iinda",
  "properties": [
    {
      "name": "textures",
      "value": "ewogICJ0aW1lc3RhbXAiIDogMTY2MzA4OTI5NDY2MywKICAicHJvZmlsZUlkIiA6ICIzZTI4YTc5ODdkNmQ0MGExYjZmN2E0NmQzODU3N2Q2MSIsCiAgInByb2ZpbGVOYW1lIiA6ICJJaW5kYSIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS82NzFjNTQxMzRlZTU5MWQzODA5NTQ4NGI3YmIyNmMwNDYzNTAzZDE2ODk2OTJhZDcyMDFiYjQ5N2ZjNmJhYjgxIiwKICAgICAgIm1ldGFkYXRhIiA6IHsKICAgICAgICAibW9kZWwiIDogInNsaW0iCiAgICAgIH0KICAgIH0KICB9Cn0=",
      "signature": "hnpM9GJDfNqdSdWFJp4yEIHbe11+ZqF0GO8+2zsT6fkixx9UdMYThhTfOC7urkps2r2JxtxrQEcGwhj/eCbTK38etOyIqom0Yegl3/OVLQs+viNg+bi4XUGXT4d+vv+SMV4zMT3qkKjkPbRo9uJtpMGVMP3EnSaVPgg7Sy8L0wRNtn+OfXfDcnh8Js8PJ0/4lVre48PongyXzDXRfciRpy3EvMqH1BYNUdEhJbJ4LsygkVDjrFZfqI4+b5/IT7ss6QF2Wk/f8Y6dJEG6oxu4dtzchbOuwghz3F0wW6NZyZCqR6ZB06R885gksjiaotTgS+FN2m1S4YN7Zb8pMtxQjPnZYZgb9F7q9kUA0wMHD1yv+4PTn/v3O6hUrYdcPxaY7MuHPXS0x2uRSfQejRSJz/WEOQEDc88QoXWUPyihGSKH/K+Pq1bFE5UmvYLmkau4MX6tAlKzCiTp73Epnk2zEOzDM1qhi7De0wJZEPJ7XyZoIKbavmdNvIl/Uk/IRPXumAOaPtDSg7KVXma4NzTvXeaZTzG/VgWqh/WHt5ntWzTGYX0A9V2y83K3jp+HJ7xY+UhAQY7CYRxgTQja+g4snRKUVBUwgl2FfBFP3Mwd/BpV729aHblN1767mHF4JPmn8HfE3QblIje2FOcLxFFaAsOcjgd113ZvMeWh2XeWkdk="
    }
  ]
}
  • Decoded value:
{
  "timestamp": 1663089294663,
  "profileId": "3e28a7987d6d40a1b6f7a46d38577d61",
  "profileName": "Iinda",
  "signatureRequired": true,
  "textures": {
    "SKIN": {
      "url": "http://textures.minecraft.net/texture/671c54134ee591d38095484b7bb26c0463503d1689692ad7201bb497fc6bab81",
      "metadata": {
        "model": "slim"
      }
    }
  }
}
  • Request Type: GET
  • Authorization: Yes
  • Response Code: 403 Forbidden
  • Response Contents: none
  • Note: from one of the commits to PolyMC, which still supports login from unmigrated accounts - it is evident that this endpoint was inaccessible for Mojang accounts at least since April 11, 2022.
  • Request Type: GET
  • Authorization: Yes
  • Response Code: 403 Forbidden
  • Response Contents: none
  • Request Type: GET
  • Authorization: Yes
  • Response Code: 403 Forbidden
  • Response Contents: none
  • Request Type: POST
  • Authorization: Yes
  • Request Payload: none
  • Response Code: 403 Forbidden
  • Response Contents: none
  • Request Type: GET
  • Authorization: Yes
  • Response Code: 403 Forbidden
  • Response Contents: none
  • Request Type: POST
  • Authorization: Yes
  • Request Payload:
{
  "variant": "classic",
  "url": "http://assets.mojang.com/SkinTemplates/steve.png"
}
  • Response Code: 403 Forbidden
  • Response Contents: none
  • Note: Using another variant of this request with multipart data as payload yielded equivalent result.
  • Request Type: DELETE
  • Authorization: Yes
  • Response Code: 403 Forbidden
  • Response Contents: none
  • Request Type: DELETE
  • Authorization: Yes
  • Response Code: 403 Forbidden
  • Response Contents: none
  • Request Type: GET
  • Authorization: Yes
  • Response Code: 204 OK
  • Response Contents: none
  • Request Type: GET
  • Authorization: Yes
  • Response Code: 403 Forbidden
  • Response Contents: none
  • Request Type: GET
  • Authorization: Yes
  • Response Code: 200 OK
  • Response Contents:
{
  "feature": "msamigration",
  "rollout": true
}
  • Request Type: POST
  • Authorization: No
  • Request Payload:
{
  "accessToken": "eyJhbGciOiJIUzI1NiJ9.eyJhZ2ciOiJBZHVsdCIsInN1YiI6IjI0N2ZhNjc4MTY3MTBiZWVkM2EzNzQzMDUwNGNlMTkwIiwibGltIjoibXNhZm9yY2VkIiwieWdndCI6Ijc2NWYxZjZhMTA4ZTQ3Y2NiMjZmMTM3NjBjMDU3ODA3IiwiaXNzIjoiWWdnZHJhc2lsLUF1dGgiLCJleHAiOjE2NjMyNjQyNjIsImlhdCI6MTY2MzA5MTQ2Mn0.AQDy2zj5fODhiQSsx8DpxNp8mOPFQ_IWDZU4nttqHwI",
  "selectedProfile": "3e28a7987d6d40a1b6f7a46d38577d61",
  "serverId": "88e16a1019277b15d58faf0541e11910eb756f6"
}
  • Response Code: 403 Forbidden
  • Response Contents:
{
  "error" : "Forbidden",
  "path" : "/session/minecraft/join"
}
  • Note: While we did not try to join "real" server and therefore could not see what hasJoined request would return on server, we assume that it would look as if the user did not try to join the server to begin with, similarly to how things work for banned accounts.

Legacy Minecraft Accounts

Thanks to the assistance of 0n#5210, we were able to perform similar tests on legacy (pre-Mojang) Minecraft account. Legacy accounts use username instead of e-mail for authentication. Results obtained are very similar to that for Mojang account. Below will be described only API requests responses to which had differences:

  • Request Type: POST
  • Authorization: No
  • Request Payload:
{
  "agent": {
    "name": "Minecraft",
    "version": 1
  },
  "username": "DinosaurBreeder",
  "password": "██████████████████",
  "requestUser": true
}
  • Response Code: 200 OK
  • Response Contents:
{
    "accessToken": "eyJhbGciOiJIUzI1NiJ9.eyJhZ2ciOiJBZHVsdCIsInN1YiI6IjMwNzIwMjIiLCJsaW0iOiJtc2Fmb3JjZWQiLCJ5Z2d0IjoiZjE0MWJiZTVhOGNkNDVkYWI2MjdlOGRlZGNiNDkyZjciLCJzcHIiOiIzMzZkYTRkMDc5ODk0NTFlODBjYWY3MGFjOGI4YzQ2NSIsImlzcyI6IllnZ2RyYXNpbC1BdXRoIiwiZmxhZ3MiOlsibXNhZm9yY2VkIl0sImV4cCI6MTY3NDQ5NDU2MiwiaWF0IjoxNjc0MzIxNzYyfQ.vowtIhklp2NumQvxF4WyFK2COo4CBJepfib0NN-rH88",
    "clientToken": "c084623015b34f01a81a0bbc64804ed1",
    "selectedProfile": {
        "name": "DinosaurBreeder",
        "id": "336da4d07989451e80caf70ac8b8c465",
        "legacy": true
    },
    "availableProfiles": [
        {
            "name": "DinosaurBreeder",
            "id": "336da4d07989451e80caf70ac8b8c465",
            "legacy": true
        }
    ],
    "user": {
        "id": "3072022",
        "username": "DinosaurBreeder"
    }
}
  • Notes: The only difference here is the presence of legacy flag in profile objects. This is also the case for https://authserver.mojang.com/refresh requests with requestUser set to true.
  • Request Type: GET
  • Authorization: No
  • Response Code: 200 OK
  • Response Contents:
{
    "id": "336da4d07989451e80caf70ac8b8c465",
    "name": "DinosaurBreeder",
    "properties": [
        {
            "name": "textures",
            "value": "ewogICJ0aW1lc3RhbXAiIDogMTY3NDMyMzcwMjQ4NSwKICAicHJvZmlsZUlkIiA6ICIzMzZkYTRkMDc5ODk0NTFlODBjYWY3MGFjOGI4YzQ2NSIsCiAgInByb2ZpbGVOYW1lIiA6ICJEaW5vc2F1ckJyZWVkZXIiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDhlYWVjYjc1MmVmN2VmZTQ3NzliYmIzYjgyZDJiYzkyNGIzNjYxYzMyZDQ3MzA0YmIzNWU2MGQyYTk1MzcxNSIsCiAgICAgICJtZXRhZGF0YSIgOiB7CiAgICAgICAgIm1vZGVsIiA6ICJzbGltIgogICAgICB9CiAgICB9CiAgfQp9",
            "signature": "N4bk0CK6rR5k7yBgXoT/SISuAY15XhrZxKZZYneBFlgjIp0YXtj4hx91twU9RYJNRAMmDYG2/RaNkfRY8Sfpv+kbDkewSEu4AnzFO2w6WT08b4glYJPoZi2gvXtpq2vnRS37KGqh3v5RjCQGztnHcZnziWenmMP6h2o88I9xziDwgOJRw1Tx7/p6qdETevnpxkdosOPIPNPi9FIjm2HV038D2H2AgACsjYHTuCpnPC+BcCmaBQzGVMYbmWUiN/+KuJoERPs06TmQlS1b3JfreT4w4vHAipgi+MXa3A1amL+vOJj2HS/Iwzah7x9VcyuwlWCaafJqQuRm1EYKMjq/tWSpzZEGgHlvyvVLibYPpbMz1ETc6JhClCfQM0iB8Iao3xMq0LfwS6Fn6Gpl+IR286OILSwoTYEnDIogj43hBQKslF0hzv0MchLoB3P08cR6KKdvcCceC8foCR8qS1bHhL5Cwmf7iarmeR7RZ3Z/4GND84ixuMRFIvfR4ymSL2Eqge5GFrQqJfvnlZc1ZV/xq1VF4i+vH1QYxVPCjtTf48TPsMHds0/ytRaAFby84Rh6SZ1nAvloXxddhuckHksVVceungk7sriovb4+JoQ/YUICXhR6ZH8gpbWwP8g5JE09XR3VNsw2V+3Sjp2nBFyNd1FxKAmMye4u3y2/BsI3pt0="
        }
    ],
    "legacy": true
}
  • Decoded value:
{
  "timestamp" : 1674323702485,
  "profileId" : "336da4d07989451e80caf70ac8b8c465",
  "profileName" : "DinosaurBreeder",
  "signatureRequired" : true,
  "textures" : {
    "SKIN" : {
      "url" : "http://textures.minecraft.net/texture/48eaecb752ef7efe4779bbb3b82d2bc924b3661c32d47304bb35e60d2a953715",
      "metadata" : {
        "model" : "slim"
      }
    }
  }
}
  • Notes: Once again, the only difference is legacy flag.
  • Request Type: GET
  • Authorization: Yes
  • Response Code: 401 Unathorized
  • Response Contents:
{
    "error": "Unauthorized",
    "errorMessage": "The request requires user authentication"
}
  • Notes: Validity of token used for authorization was double-checked.

As you can observe, the only differences for legacy accounts are that they can be publicly and privately identified as legacy, as well as inaccessibility of /user/security/location API endpoint. All conclusions drawn below hold valid for both legacy and Mojang accounts.

Conclusions

With this data on hand it is relatevely easy to answer our initial questions.

  1. Can name and UUID of the account be established with accounts credentials (e-mail & password)?

Yes, as evidenced by Authentication - Request 1. Successful authentication via that endpoint seems to always yield UUID and username as part of received response.

  1. Can access tokens still be obtained for unmigrated account?

Yes, they too are received through authenticate request. This is used by minecraft.net in particular to handle login into unmigrated accounts, although request payload is slightly different in that case.

  1. If above is true, is it possible to verify validity of such tokens later?

Yes, see Authentication - Request 2. While most API endpoints respond with 403 Forbidden when trying to use access token for unmigrated account - that can also be used to establish validity of the token, as for invalid tokens they return 401 Unauthorized.

  1. Can name and UUID of the account be established with access token alone?

No. This would normally be accomplished in Mojang API - Request 4, but since that no longer works for unmigrated accounts, there are only 2 ways that remain - authenticate and refresh requests against https://authserver.mojang.com/. First one requires credentials. Second is closer to goal, but still needs original client token in addition to access token. Performing request without client token yields 403 Forbidden response with following contents:

{
  "error": "ForbiddenOperationException",
  "errorMessage": "Missing clientToken."
}
  1. Is it possible to establish what skin and cape of the account are, and how?

Yes, as shown in Mojang API - Request 3. All you need to perform this request is account's UUID, which can be obtained directly during authentication, or indirectly via Mojang API - Request 1 if only username is known. It is therefore possible for both account owner and other players to find out its skin and cape.

  1. Is it indeed impossible to join multiplayer servers with unmigrated account?

Yes, see Mojang API - Request 15. It's worth noting that Mojang accounts can still host LAN games, due to the fact integrated server never questions legitimacy of its owner. In the light of Mojang API - Request 3 succeeding all joining players will also be able to see owner's skin and cape.

  1. Is it possible to get banned while playing from unmigrated account?

To clarify scope of the question - while it is not possible for unmigrated accounts to join online-mode servers, they can still play on offline-mode servers, or those that alter requirements for authentication in other ways. The question therefore becomes "can unmigrated accounts be reported and subsequently banned while playing on such servers?".

To make that possible, unmigrated accounts would need to have access to their chat signing keypair, which would be used by client to sign their chat messages and therefore produce potentially incriminating evidence necessary to incur a ban. Our attempts to fetch that keypair in Mojang API - Request 7 have failed; therefore, unmigrated accounts cannot produce any such evidence, not even in principle.

  1. With full access, is it possible to change account's name, skin or cape?

No, see requests 9/10/11 in Mojang API section. While we did not perform specific request to change account's name, it seems highly improbable that it would succeed where everything else failed.

  1. With full access, is it possible to change account's e-mail or password?

No known API endpoints exist for this, and it does not seem like anything can be done on minecraft.net to achieve that, except initiating the migration.

  1. Can trustless authentication schemes (key-based and skin-based) be used to verify unmigrated accounts?

Unfortunately - no, since chat signing keypair cannot be obtained and skin cannot be changed with unmigrated account. While you can hand access token to a verifier for direct validation against Mojang's services, you'd have to trust verifier to not misuse it. Even though there is very little that can be done with unmigrated account's access token, if we assume that there exist multiple servers that require you to expose access token as part of login process, by joining one of them you effectively expose information sufficient to log into any other one under your name.

In theory, it is possible to create a single centralized authentication service instead, which would accept tokens from clients for validation and assure servers that joining user is legitimate without exposing the token. That, however, would bring forth many issues that come with centralized system like that, as it would have to be trusted to operate in good faith, and if it is ever taken down - whole network would collapse.

Some of those issues can be alleviated by using distributed consensus network for all data storage instead, wherein every player will publish public key from special keypair generated for the purposes of server authentication, and central authority will only be responsible for issuing signed statements about account ownership for key holders. Such solution would be less vulnerable to abuse and external attacks, but some presence of centralization and problems that come with it is unavoidable in any implementation.

  1. How can answers to the above change in future?

Alas, the outlook here is bleak. While unauthorized API endpoints can still be used to establish name, UUID and skin/cape of the account - Mojang can take that away at any time, effectively deleting legacy accounts from public record. Those records might persist on third-party services that employ caching, but there will be no guarantee of legitimacy of such records (i.e. any such service would be able to alter, remove or inject statements about legacy accounts into data it serves).

Authentication endpoints remain fully functional so far, and since those are necessary for login on minecraft.net - it is much more likely that they will persist. The amount of data they allow to extract about the account can be severely reduced, however. Even username and UUID are not required to provide functionality currently available to unmigrated accounts.

It should remain possible to obtain and validate access tokens in order for login and migration to be available on Minecraft's website. However, LapisDemon raised a valid concern that Mojang could, at least in principle, remove even that. From there they could allow to migrate accounts only manually via direct communication with support, or even stop offering migration at all. Legality of such decision would be questionable, but so is this whole affair with forced migration and acceptance of Microsoft's service terms in the first place, and I am no lawyer to assess such matters for any given jurisdiction.

@thennothinghappened
Copy link

thennothinghappened commented Dec 24, 2022

one more thing to look into is account.mojang.com
mentioning that as from there you can still change email and password, I did that on my account recently
Screenshot_20221224-163558__01__01

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment