games647 / FastLogin

Checks if a minecraft player has a valid paid account. If so, they can skip offline authentication automatically. (premium auto login)
https://www.spigotmc.org/resources/fastlogin.14153
MIT License
497 stars 121 forks source link

FastLogin Crash with /premium #258

Closed NoahSehnsucht closed 5 years ago

NoahSehnsucht commented 5 years ago

What behaviour is observed:

//: #Command /premium it's crashing

What behaviour is expected:

//: # The command was succesfuly executed

Steps/models to reproduce:

//: #Trying execute the command /premium

Plugin list:

//: # LuckPerms, TitleManager, FastAsyncWorldEdit, ProtocolLib, AuthMe, ExploitFixer, WorldEdit, FastLogin, LiteBans, WorldGuard

Environment description

//: # Minecraft 1.8.9, MySQL

Plugin version or build number (don't write latest):

//: # FastLogin version 1.11-SNAPSHOT-4110ce2

Error Log:

//: #[SEVERE] Task BungeeTask(sched=net.md_5.bungee.scheduler.BungeeScheduler@97e93f1, id=96, owner=com.github.games647.fastlogin.bungee.FastLoginBungee@143d9a93, task=com.github.games647.fastlogin.bungee.listener.PluginMessageListener$$Lambda$258/1148334103@23210ba4, delay=0, period=0, running=true) encountered an exception java.lang.StackOverflowError at java.io.StringWriter.append(StringWriter.java:143) at java.io.StringWriter.append(StringWriter.java:41) at com.google.gson.stream.JsonWriter.beforeValue(JsonWriter.java:651) at com.google.gson.stream.JsonWriter.open(JsonWriter.java:325) at com.google.gson.stream.JsonWriter.beginArray(JsonWriter.java:288) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:95) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:125) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:243) at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:976) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:125) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:243) at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:976) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:97) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:125) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:243) at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:976) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:125) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:243) at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:976) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:97) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:125) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:243) at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:976) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:125) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:243) at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:976) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:97) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:125) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:243) at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:976) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:125) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:243) at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:976) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:97) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:125) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:243) at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:976)

Configuration:

//: ## FastLogin config

Project site: https://www.spigotmc.org/resources/fastlogin.14153

Source code: https://github.com/games647/FastLogin

#

You can access the newest config here:

https://github.com/games647/FastLogin/blob/master/core/src/main/resources/config.yml

Request a premium login without forcing the player to type a command

#

If you activate autoRegister, this plugin will check/do these points on login:

1. An existing cracked account shouldn't exist

-> paid accounts cannot steal the existing account of cracked players

- (Already registered players could still use the /premium command to activate premium checks)

2. Automatically registers an account with a strong random generated password

-> cracked player cannot register an account for the premium player and so cannot the steal the account

#

Furthermore the premium player check have to be made based on the player name

This means if a cracked player connects to the server and we request a paid account login from this player

the player just disconnect and sees the message: 'bad login' or 'invalid session'

There is no way to change this message

For more information: https://github.com/games647/FastLogin#why-do-players-have-to-invoke-a-command

autoRegister: false

This is extra configuration option to the feature above. If we request a premium authentication from a player who

isn't actual premium but used a premium username, the player will disconnect with the reason "invalid session" or

"bad login".

#

If you activate this, we are remembering this player and do not force another premium authentication if the player

tries to join again, so the player could join as cracked player.

secondAttemptCracked: false

New cracked players will be kicked from server. Good if you want switch from offline-mode to online-mode without

losing players!

#

Existing cracked and premium players could still join your server. Moreover you could add playernames to a whitelist.

So that these cracked players could join too although they are new players.

switchMode: false

If this plugin detected that a player has a premium, it can also set the associated

uuid from that account. So if the player changes the username, they will still have

the same player data (inventory, permissions, ...)

#

Warning: This also means that the UUID will be different if the player is connecting

through a offline mode connection. This could cause plugin compatibility issues.

#

This is a example and doesn't apply for every plugin.

Example: If you want to ban players who aren't online at the moment, the ban plugin will look

after a offline uuid associated to the player, because the server is in offline mode. Then the premium

players could still join the server, because they have different UUID.

#

Moreover you may want to convert the offline UUID to a premium UUID. This will ensure that the player

will have the same inventory, permissions, ... if they switched to premium authentication from offline/cracked

authentication.

#

This feature requires Cauldron, Spigot or a fork of Spigot (Paper)

premiumUuid: false

This will make an additional check (only for player names which are not in the database) against the mojang servers

in order to get the premium UUID. If that premium UUID is in the database, we can assume on successful login that the

player changed it's username and we just update the name in the database.

Examples:

Case 1

nameChangeCheck = false ----- autoRegister = false

#

GameProfile logins as cracked until the player invoked the command /premium. Then we could override the existing

database record.

#

Case 2

#

nameChangeCheck = true ----- autoRegister = false

#

Connect the Mojang API and check what UUID the player has (UUID exists => Paid Minecraft account). If that UUID is in

the database it's an existing player and FastLogin can assume the player is premium and changed the username.

If it's not in the database, it's a new player and could be a cracked player. So we just use a offline mode

authentication for this player.

#

Limitation: Cracked players who uses the new username of a paid account cannot join the server if the database

contains the old name. (Example: The owner of the paid account no longer plays on the server, but changed the username

in the meanwhile).

#

Case 3

#

nameChangeCheck = false ----- autoRegister = true

#

We will always request a premium authentication if the username is unknown to us, but is in use by a paid Minecraft

account. This means it's kind of a more aggressive check like nameChangeCheck = true and autoRegister = false, because

it request a premium authentication which are completely new to us, that even the premium UUID is not in our database.

#

Limitation: see below

#

Case 4

#

nameChangeCheck = true ----- autoRegister = true

#

Based on autoRegister it checks if the player name is premium and login using a premium authentication. After that

fastlogin receives the premium UUID and can update the database record.

#

Limitation from autoRegister: New offline players who uses the username of an existing Minecraft cannot join the

server.

nameChangeCheck: false

If your players have a premium account and a skin associated to their account, this plugin

can download the data and set it to the online player.

#

Keep in mind that this will only works if the player:

* is the owner of the premium account

* the server connection is established through a premium connection (paid account authentication)

* has a skin

#

This means this plugin doesn't need to create a new connection to the Mojang servers, because

the skin data is included in the Auth-Verification-Response sent by Mojang. If you want to use for other

players like cracked player, you have to use other plugins.

#

If you want to use skins for your cracked player, you need an additional plugin like

ChangeSkin, SkinRestorer, ...

forwardSkin: true

Displays a warning message that this message SHOULD only be invoked by

users who actually are the owner of this account. So not by cracked players

#

If they still want to invoke the command, they have to invoke /premium again

premium-warning: true

If you have autoRegister or nameChangeCheck enabled, you could be rate-limited by Mojang.

The requests of the both options will be only made by FastLogin if the username is unknown to the server

You are allowed to make 600 requests per 10-minutes (60 per minute)

If you own a big server this value could be too low

Once the limit is reached, new players are always logged in as cracked until the rate-limit is expired.

(to the next ten minutes)

#

The limit is IP-wide. If you have multiple IPv4-addresses you specify them here. FastLogin will then use it in

rotating order --> 5 different IP-addresses 5 * 600 per 10 minutes

If this list is empty only the default one will be used

#

Lists are created like this:

ip-addresses:

- 192-168-0-2

ip-addresses: []

How many requests should be established to the Mojang API for Name -> UUID requests. Some other plugins as well

as the head Minecraft block make such requests as well. Using this option you can limit the amount requests this

plugin should make.

#

If you lower this value, other plugins could still make requests while FastLogin cannot.

Mojang limits the amount of request to 600 per 10 minutes per IPv4-address.

mojang-request-limit: 600

This option automatically registers players which are in the FastLogin database, but not in the auth plugin database.

This can happen if you switch your auth plugin or cleared the database of the auth plugin.

https://github.com/games647/FastLogin/issues/85

auto-register-unknown: false

This disables the auto login from fastlogin. So a premium (like a paid account) authentication is requested, but

the player won't be auto logged into the account.

#

This can be used as 2Factor authentication for better security of your accounts. A hacker then needs both passwords.

The password of your Minecraft and the password to login in with your auth plugin

autoLogin: true

Database configuration

Recommended is the use of MariaDB (a better version of MySQL)

Single file SQLite database

driver: org.sqlite.JDBC

File location

database: '{pluginDir}/FastLogin.db'

MySQL/MariaDB

If you want to enable it uncomment only the lines below this not this line.

driver: com.mysql.jdbc.Driver host: 127.0.0.1 port: 3306 database: fastlogin username: No. password: No

Advanced Connection Pool settings in seconds

timeout: 30

lifetime: 30

It's strongly recommended to enable SSL and setup a SSL certificate if the MySQL server isn't running on the same

machine

useSSL: false

HTTP proxies for connecting to the Mojang servers in order to check if the username of a player is premium.

This is a workaround to prevent rate-limiting by Mojang. These proxies will only be used once your server hit

the rate-limit or the custom value above.

Please make sure you use reliable proxies.

proxies:

'IP:Port' or 'Domain:Port'

- 'xyz.com:1337'

- 'test.com:5131'

NoahSehnsucht commented 5 years ago

hi?

games647 commented 5 years ago

Duplicate #254