Skip to content

Add docs for using builtin auth mechanism#10719

Open
baccenfutter wants to merge 1 commit intogodotengine:masterfrom
baccenfutter:high-level-multiplayer-authentication
Open

Add docs for using builtin auth mechanism#10719
baccenfutter wants to merge 1 commit intogodotengine:masterfrom
baccenfutter:high-level-multiplayer-authentication

Conversation

@baccenfutter
Copy link

@baccenfutter baccenfutter commented Feb 26, 2025

Took a huge unnecessary detour, today. it was an upstream battle...

Since there was no mention of it whatsoever, I intuitively concluded that I would have to build my own authentication on top of SceneMultiplayer. The authentication part was easy, but when trying to figure out how to hook into Godot's RPC call-stack to prevent unauthenticated RPC calls, I got stuck and was made aware of SceneMultiplayer.auth_callback by Discord.

Getting the builtin auth mechanism to work with the available docs on SceneMultiplayer was an upstream battle.

But the main issue to me, is the complete lack of mentioning the availability of the builtin auth mechanism, at all.

Wanted to share my results and prevent others from having to take the same detour.

@baccenfutter baccenfutter force-pushed the high-level-multiplayer-authentication branch 2 times, most recently from 04ec47d to bfa5410 Compare February 26, 2025 23:59
@skyace65 skyace65 added enhancement area:manual Issues and PRs related to the Manual/Tutorials section of the documentation topic:network labels Feb 27, 2025
@SchnozzleCat
Copy link

SchnozzleCat commented Jun 7, 2025

In addition to discoverability of the authentication mechanism being low, there also appears to be misleading information in the relevant documentation.

The SceneMultiplayer authentication docs (specifically the docs for peer_authenticating and complete_auth) seem to imply that any given peer does not receive the peer_connected signal for another peer until it has authenticated with that specific peer (by both of them calling complete_auth on each other's peer IDs), but that is not what is happening from what I can tell.

I can only see the authentication handshake happen between a client peer and the server, and once the authentication with the server has completed, peer_connected signals are emitted for all others peers on a peer, even though complete_auth was never called for those peers.

I'm not terribly familiar with the godot source code, but that also appears to be what is happening. _admit_peer checks if the server is calling the function, and if so, forwards peer IDs to other peers. Clients receive this message, check that they aren't the server, and that the message came from the server, and then add the peers. The comment in the code also indicates that these peer connection messages are just being relayed over the server (if relaying is enabled), and the clients automatically accept the peers, without authenticating first.

Ideally the previously mentioned documentation can also be updated as part of this PR to make the entire mechanism more clear.

# signal to the MultiplayerAPI that the authentication was successful
multiplayer.complete_auth(peer_id)

As soon as both, the client's and the the server's :ref:`complete_auth() <class_SceneMultiplayer_method_complete_auth>`, have been called, the connection is considered to be established and the `connected_to_server` and `peer_connected` signals fire.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
As soon as both, the client's and the the server's :ref:`complete_auth() <class_SceneMultiplayer_method_complete_auth>`, have been called, the connection is considered to be established and the `connected_to_server` and `peer_connected` signals fire.
As soon as both, the client's and the server's :ref:`complete_auth() <class_SceneMultiplayer_method_complete_auth>`,
have been called, the connection is considered to be established and the
`connected_to_server` and `peer_connected` signals fire.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather:

Suggested change
As soon as both, the client's and the the server's :ref:`complete_auth() <class_SceneMultiplayer_method_complete_auth>`, have been called, the connection is considered to be established and the `connected_to_server` and `peer_connected` signals fire.
As soon as both the client's and the server's :ref:`complete_auth() <class_SceneMultiplayer_method_complete_auth>` methods
have been called, the connection is considered to be established and the
`connected_to_server` and `peer_connected` signals fire.

Too many commas

Comment on lines +677 to +678
Before hosting your game online to a public audience, you may want to consider adding authentication and protecting your RPCs against unauthenticated access.
For this you can use the :ref:`SceneMultiplayer <class_SceneMultiplayer>`'s builtin authentication mechanism.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Before hosting your game online to a public audience, you may want to consider adding authentication and protecting your RPCs against unauthenticated access.
For this you can use the :ref:`SceneMultiplayer <class_SceneMultiplayer>`'s builtin authentication mechanism.
Before hosting your game online to a public audience, you may want to consider adding authentication and protecting your RPCs against unauthenticated access.
You can use the :ref:`SceneMultiplayer <class_SceneMultiplayer>`'s builtin authentication mechanism for this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We generally use built-in as well afaik

.. tabs::
.. code-tab:: gdscript GDScript

# after multiplayer.multiplayer_peer = peer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# after multiplayer.multiplayer_peer = peer
# This goes after `multiplayer.multiplayer_peer = peer`.

multiplayer.auth_timout = 3
multiplayer.auth_callback = func(peer_id: int, payload: PackedByteArray):
var auth_data: Dictionary = JSON.parse_string(payload.get_string_from_utf8())
# your authentication logic goes here...
Copy link
Member

@Calinou Calinou Jul 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# your authentication logic goes here...
# Your authentication logic (such as checking the supplied username/password against a database)
# goes here.

var auth_data: Dictionary = JSON.parse_string(payload.get_string_from_utf8())
# your authentication logic goes here...

# signal to the MultiplayerAPI that the authentication was successful
Copy link
Member

@Calinou Calinou Jul 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Signal" may be confused with emitting a signal here.

Suggested change
# signal to the MultiplayerAPI that the authentication was successful
# Tell the MultiplayerAPI that the authentication was successful.

.. tabs::
.. code-tab:: gdscript GDScript

# after multiplayer.multiplayer_peer = peer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# after multiplayer.multiplayer_peer = peer
# This goes after `multiplayer.multiplayer_peer = peer`.


# after multiplayer.multiplayer_peer = peer
multiplayer.auth_callback = func:
# we have to set this on the client in order for the peer_authenticating signal to fire
Copy link
Member

@Calinou Calinou Jul 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# we have to set this on the client in order for the peer_authenticating signal to fire
# We have to set this on the client for the `peer_authenticating`
# signal to emit.

}
multiplayer.send_auth(1, JSON.stringify(auth_data).to_utf8_buffer())

# signal to the MultiplayerAPI that the authentication was successful
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# signal to the MultiplayerAPI that the authentication was successful
# Tell the MultiplayerAPI that the authentication was successful.

@alliephante
Copy link

Might I suggest not using lambda in your examples? It's a lot cleaner and easier to follow if the method being linked is distinct.

# signal to the MultiplayerAPI that the authentication was successful
multiplayer.complete_auth(peer_id)

As soon as both, the client's and the the server's :ref:`complete_auth() <class_SceneMultiplayer_method_complete_auth>`, have been called, the connection is considered to be established and the `connected_to_server` and `peer_connected` signals fire.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather:

Suggested change
As soon as both, the client's and the the server's :ref:`complete_auth() <class_SceneMultiplayer_method_complete_auth>`, have been called, the connection is considered to be established and the `connected_to_server` and `peer_connected` signals fire.
As soon as both the client's and the server's :ref:`complete_auth() <class_SceneMultiplayer_method_complete_auth>` methods
have been called, the connection is considered to be established and the
`connected_to_server` and `peer_connected` signals fire.

Too many commas

Comment on lines +705 to +712
var auth_data = {
"username": "username",
"password": "password",
}
multiplayer.send_auth(1, JSON.stringify(auth_data).to_utf8_buffer())

# signal to the MultiplayerAPI that the authentication was successful
multiplayer.complete_auth(peer_id)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var auth_data = {
"username": "username",
"password": "password",
}
multiplayer.send_auth(1, JSON.stringify(auth_data).to_utf8_buffer())
# signal to the MultiplayerAPI that the authentication was successful
multiplayer.complete_auth(peer_id)
var auth_data = {
"username": "username",
"password": "password",
}
multiplayer.send_auth(1, JSON.stringify(auth_data).to_utf8_buffer())
# Tell the MultiplayerAPI that the authentication was successful.
multiplayer.complete_auth(peer_id)

Continuation for a method uses two indentations, see the style guide

Comment on lines +688 to +693
var auth_data: Dictionary = JSON.parse_string(payload.get_string_from_utf8())
# your authentication logic goes here...

# signal to the MultiplayerAPI that the authentication was successful
if authentication_successful:
multiplayer.complete_auth(peer_id)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var auth_data: Dictionary = JSON.parse_string(payload.get_string_from_utf8())
# your authentication logic goes here...
# signal to the MultiplayerAPI that the authentication was successful
if authentication_successful:
multiplayer.complete_auth(peer_id)
var auth_data: Dictionary = JSON.parse_string(payload.get_string_from_utf8())
# Your authentication logic (such as checking the supplied username/password against a database)
# goes here.
# Tell the MultiplayerAPI that the authentication was successful.
if authentication_successful:
multiplayer.complete_auth(peer_id)

Comment on lines +677 to +678
Before hosting your game online to a public audience, you may want to consider adding authentication and protecting your RPCs against unauthenticated access.
For this you can use the :ref:`SceneMultiplayer <class_SceneMultiplayer>`'s builtin authentication mechanism.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We generally use built-in as well afaik

Comment on lines +702 to +703
# we have to set this on the client in order for the peer_authenticating signal to fire
pass
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# we have to set this on the client in order for the peer_authenticating signal to fire
pass
# We have to set this on the client for the `peer_authenticating`
# signal to emit.
pass

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

Labels

area:manual Issues and PRs related to the Manual/Tutorials section of the documentation enhancement topic:network

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Misleading documentation for SceneMultiplayer authentication

6 participants