TeleportService.AllowClientTeleports

As a Roblox developer, it is currently impossible to block the client from utilising teleport methods from the TeleportService. As such, I would like a boolean property under the TeleportService called AllowClientTeleports. AllowClientTeleports would be defaulted to true on production in order to remain a non-intrusive update and for developers to opt-in if they feel it would better fit their games.

This property fairly self explanatory; if the property is true, clients can use TeleportService methods that are supported client-side. If the property is false, clients will be thrown an error in attempting to use client-supported teleport methods (much like when attempting to use any other server-sided method).

For the sake of understanding what I am referencing when I say teleport methods, I am not referring to all methods under the TeleportService. I am only referring to the ones which can transfer players between places and instances, which are able to be used by the client.

Let’s get to know your problem.
Multi-place games are becoming fairly common on Roblox, which means that users are being teleported between places when reaching certain conditions. As a developer currently working on several upcoming games incorporating multiple places and needing to teleport between them, I would like to block the client from using teleport methods.

Why though? How does this help you?
On top of ensuring that clients don’t mistakenly teleport to other places, I can stop exploiters from traversing my game without my server’s explicit clear to do so.

I feel that, by extension of needing a workaround to combat this, it is counterintuitive to vet players when they enter a place based on conditions that I need to retrieve through DataStores. Ephemeral DataStores may help out but we don’t know anything about how they’ll go down and even when they’re out, using them would still be counterintuitive.

Wait. Just use server-sided teleport data or MessagingService.
Doesn’t change the fact that the workflow is counterintuitive. In fact, using these or any other cross-instance method is completely pointless. A client teleport can easily circumvent server-based conditions and exploiters wouldn’t need to do a thing except call teleport.

MessagingService could work only if you’re willing to send a message to literally every existing instance in every place of your game with a conditional lock after a player leaves and cache that, then delete the result after a long while. See how unreliable and counterintuitive that is? Very.

Could you provide an example scenario to help us better understand?
Yes of course. I have a place, PlaceB that requires a certain level to enter it, 20. Players spawn in at a lobby world, PlaceA. Realistically a client can’t teleport to PlaceB with some checks, no, but a faulty codebase or exploited client can easily bypass that restriction.

Current workflow:

  • Player1 wants to enter PlaceB from PlaceA.
  • Server checks if Player1’s level is above 20. It’s not. They aren’t teleported.
  • Sneaky Player2 calls Teleport to PlaceB from PlaceA and bypasses the check.
  • PlaceB has a script that checks the player’s level when they enter.
  • PlaceB pointlessly spends a Get request to a DataStore, only to kick the player if their level isn’t high enough.

Workflow with AllowClientTeleports:

  • AllowClientTeleports is set to false in Studio.
  • Sneaky Player2 is back and calls Teleport to PlaceB from PlaceA.
  • Client is thrown an error - cannot access TeleportService method.

See how the workflow is reduced by a lot? Instead of going through the hassle of covering for cases where a player teleports illegally to another destination, you simply disallow client-based teleports and you go on your merry way with your usual server workflow for vetting players.


That’s all, really. A feature request exists like this and explains it in a concise manner compared to this, however I didn’t reply there for three reasons.

  • I already started writing before I saw it. I didn’t want to take the time to re-tailor my post to say “support, this is relevant now, I’d like this feature”.

  • That thread is 3-years old. It’s not a necrobump if you’re adding new information, but I’m not particularly comfortable in adding a post to a thread created that long ago.

  • I’m asking for an engine feature, not a game setting. It fits more as a property in TeleportService than as a game setting, frankly. It can be a game setting too though that just flips the property, much like “Allow HTTP Requests”.

I could’ve. I probably should’ve too. But I didn’t. Take this thread for now.

59 Likes

While I do like this idea, why are you simply unable to add in sanity check when the player arrives in the server with PlayerAdded? If players joining other places within your universe is really a major concern, then you could easily resolve the issue yourself.

I thought someone might ask this question, which is why I took the time to very clearly explain why this workflow is unintuitive in the thread.

A client initiated teleport bypasses any kind of check on the sending server, which means now that I have to vet the receiving server. The receiving server isn’t able to determine if a player arrived from a teleport, only that they joined the server. And now I have to implement pointless checks to redirect a player out.

It’s not intuitive, useful or worth the time at all to create extra processes in your receiving place because a player might have entered without appropriate permission. In the case of data-based places, you now spend extra requests on a single bad client; if they do this rapidly, they can throttle DataStores.

You can simply disable client teleports and be done with it. It is much more intuitive, easy and helpful to disallow clients to teleport over covering for cases of illegal teleports in your games. It also opens the realm of using server-sided teleport data to transfer information between places (not sensitive data, but still data at all), while a client teleport can fake or skip that at all.

2 Likes

I wasn’t suggesting checking the teleport data but rather the fact that you can just use the PlayerAdded event. Regardless of the player teleported from the client or the server, that event should still fire. I really don’t understand why a few lines of code is unintuitive when it’ll be critically important to your game.

However, my point still stands. I really do like your idea. In regards to your current workflow, it’ll be very easy to simply check their level against the required level. I do understand your perspective on it but I feel like the provided use case isn’t really a strong enough reason for such a functionality as you can easily do it yourself.

Wanted to update this post a little, since a recent related post was raised to my attention. I still don’t intend to respond to the above post since I’ve already given a response as to why this response is bad AND battled it out on Discord - in short, it’s completely against my use case, counterintuitive and unhelpful. I don’t care to parrot points when they won’t be heeded.

Right now, I’m relying on a method that @IntegerUnderflow mentioned. Since it’s on the DevForum Discord people may not have access to it, but for the sake of sharing the method to anyone else experiencing battles with clients being allowed to teleport, here:

Currently, I’m following this advice. I’ve yet to test it in a live production environment but the rest of the flow is working perfectly for me. Still doesn’t resolve the initial issue, but it’s worth a start. I follow this method almost to a T. As for the hash method, I use a pure Lua implement of SHA256.

https://gist.github.com/dannysmc95/956327d65a0e47182638

Overall, I’ve written my workflow to a Roblox script and archived it for future reference. The script is not a public model and as such, I’ll simply take a screenshot of its contents. It’s meant to be an outline for how I’ve followed this advice. Another shout for Dekkonot and AMD_chan for helping me resolve some misunderstandings about the application of this.

Ignore the annoying blue underlines.

This is serving as a temporary “workaround” for “disallowing” client-based teleports. Clients can’t make teleports without knowing the secret (the server salting), which is a server-side constant that the client can NEVER see unless they have edit access to the game. That’s the key part to this method. Therefore, when they arrive and the hash doesn’t match, they’re kicked for a key mismatch.

15 Likes

Current workflow:

  • Player1 wants to enter PlaceB from PlaceA.
  • Server checks if Player1’s level is above 20. It’s not. They aren’t teleported.
  • Sneaky Player2 calls Teleport to PlaceB from PlaceA and bypasses the check.
  • PlaceB has a script that checks the player’s level when they enter.
  • Sneaky Player2 loads all assets of the game, being able to leak / copy anything he wants!
    • Not really cool if you have testing place under your main game which only certain people with extra access can join, test and give feedback to.
  • PlaceB pointlessly spends a Get request to a DataStore, only to kick the player if their level isn’t high enough.

Little edit to the original post, another reason why this would be much more appreciated. Kicking player won’t be denied his access to already loaded data from the place.

Was going to post this as my own feature request, although I found this one when doing my final searches

As a Roblox developer, it is currently too hard to secure an upcoming sub-place for an already released game. Currently, multiple different TeleportService functions allow teleporting to be initiated from the client. This is a problem as exploiters commonly fake teleport initiations to access content early.

Kicking is not a solution. Exploiters can simply hide the overlaying kick message and expose all the loaded assets in Workspace. Not replicating instances is also too difficult. Due to how everything in Workspace is always replicated from the server to the client, assets are always being sent to the client as they join. Storing these assets elsewhere could break current code, creating innaccurate error logs when exploiters join.

This issue is all amplified by the fact that the current documentation for Teleporting Between Places implies that teleporting can only be initiated via the server to ‘reduce client exploitation’.

This has led many developers with front-page experiences to believe that teleport service is secure from client-based teleports, which is not true as legacy functions still pemit teleporting on the client. I have had multiple front-page devs try to argue this to me.

If this issue is addressed, it would improve my development experience because I would no longer have to use needless workarounds such as developing in an entirely different game until I’m getting ready to publish.

10 Likes

Is this still not an actual feature? Why are clients able to teleport to places without the server’s permission? Can this be looked at and addressed? The current workarounds for this are incredibly frustrating.

5 Likes