Skip to content

Authentication

To authenticate clients, you can bring your own token validation logic by implementing the onAuth() method in your room.

Authentication module

The new Authentication module provides a set of tools to help you authenticate your players into your application. (Currently in beta, feedback is welcome on colyseus/colyseus#657)

Room authentication

To authenticate clients into a room, you must implement the onAuth() method in your room. This method is called before onCreate() or onJoin(), and it is responsible for validating the client's authentication token.

Client-side

The authentication token set on client.auth.token will be sent as Authorization header in all http requests to the server, including matchmaking requests.

// set the auth token
client.auth.token = "YOUR AUTH TOKEN";

// matchmaking requests will contain the auth token
client.joinOrCreate("my_room").then((room) => {
    console.log(room);
});

// http requests will contain the auth token
client.http.get("/profile").then((response) => {
  console.log(response.data);
});

Server-side

import { Room } from "colyseus";
import { JWT } from "@colyseus/auth";

class MyRoom extends Room {
    static async onAuth (token, request) {
        return await JWT.verify(token);
    }
}
import { Room } from "colyseus";
import { DecodedIdToken, getAuth } from "firebase-admin/auth";

class MyRoom extends Room {
    static onAuth(token, req) {
        return getAuth().verifyIdToken(token);
    }
}

onAuth (client, options, request)

onAuth may be implemented either as static or instance method.

Since version 0.15.14, it is recommended to use the static version onAuth() method, though you may still use the onAuth as instance method. We're getting feedback about new authentication module here: colyseus/colyseus#660

The onAuth() method will be executed before onJoin(). It can be used to verify authenticity of a client joining the room.

  • If onAuth() returns a truthy value, onJoin() is going to be called with the returned value as the third argument.
  • If onAuth() returns a falsy value, the client is immediatelly rejected, causing the matchmaking function call from the client-side to fail.
  • You may also throw a ServerError to expose a custom error to be handled in the client-side.

If left non-implemented, it always returns true - allowing any client to connect.

Getting player's IP address

You can use the request variable to retrieve the user's IP address, http headers, and more. E.g.: request.headers['x-forwarded-for'] || request.socket.remoteAddress

Implementations examples

import { Room, ServerError } from "colyseus";

class MyRoom extends Room {
  async onAuth (client, options, request) {
    /**
     * Alternatively, you can use `async` / `await`,
     * which will return a `Promise` under the hood.
     */
    const userData = await validateToken(options.accessToken);
    if (userData) {
        return userData;

    } else {
        throw new ServerError(400, "bad access token");
    }
  }
}
import { Room } from "colyseus";

class MyRoom extends Room {
  onAuth (client, options, request): boolean {
    /**
     * You can immediatelly return a `boolean` value.
     */
     if (options.password === "secret") {
       return true;

     } else {
       throw new ServerError(400, "bad access token");
     }
  }
}
import { Room } from "colyseus";

class MyRoom extends Room {
  onAuth (client, options, request): Promise<any> {
    /**
     * You can return a `Promise`, and perform some asynchronous task to validate the client.
     */
    return new Promise((resolve, reject) => {
      validateToken(options.accessToken, (err, userData) => {
        if (!err) {
          resolve(userData);
        } else {
          reject(new ServerError(400, "bad access token"));
        }
      });
    });
  }
}

Client-side examples

From the client-side, you may call the matchmaking method (join, joinOrCreate, etc) with a token from some authentication service of your choice (i. e. Facebook):

client.joinOrCreate("world", {
  accessToken: yourFacebookAccessToken

}).then((room) => {
  // success

}).catch((err) => {
  // handle error...
  err.code // 400
  err.message // "bad access token"
});
try {
  var room = await client.JoinOrCreate<YourStateClass>("world", new {
    accessToken = yourFacebookAccessToken
  });
  // success

} catch (err) {
  // handle error...
  err.code // 400
  err.message // "bad access token"
}
client:join_or_create("world", {
  accessToken = yourFacebookAccessToken

}, function(err, room)
  if err then
    -- handle error...
    err.code -- 400
    err.message -- "bad access token"
    return
  end

  -- success
end)
client.joinOrCreate("world", {
  accessToken: yourFacebookAccessToken

}, YourStateClass, function (err, room) {
  if (err != null) {
    // handle error...
    err.code // 400
    err.message // "bad access token"
    return;
  }

  // success
})
client.joinOrCreate("world", {
  { "accessToken", yourFacebookAccessToken }

}, [=](MatchMakeError *err, Room<YourStateClass>* room) {
  if (err != "") {
    // handle error...
    err.code // 400
    err.message // "bad access token"
    return;
  }

  // success
});