uNITY DEVELOPER

tECHNICAL GAME DESIGNER

uNITY DEVELOPER

tECHNICAL GAME DESIGNER

Credentials security

Security

Sep 26, 2025

Theo Garnon

Credentials are pieces of data, often stored in JSON format, that serve as access keys granting certain read and/or write permissions on a database. This information is considered sensitive and must be protected to prevent any potential vulnerability or intrusion within the project’s data.

For 8GameLearn, we use Google Cloud Storage to store the game data created by the subject matter experts.

To obtain write permissions on the bucket—so we can save and modify games—we need credentials. The most straightforward solution would be to store them directly in Unity and use them for requests to the bucket.

However, anyone who decompiled the project would gain access to these credentials, which would represent a major security risk.

PROBLEM

How can we obtain modification rights without exposing the credentials and without storing them on the client side?

SOLUTION

Store the credentials on a remote server that distributes a unique access token valid for one hour.

A Node.js server requests a token from Google Cloud using the stored credentials. As a result, the client only receives this short-lived token, which is distributed based on application-specific rules — preventing a potential attacker from impersonating our app.

Currently, this Node.js server is hosted on Railway, since PlayFab CloudScript unfortunately does not support Node.js.
In the future, hosting it directly on Google Cloud would be a logical step to streamline data management for the project.

// index.tsx
import { Hono } from "hono@4";
import { cors } from "hono/cors";
import { GoogleAuth } from "google-auth-library";

const app = new Hono();

// CORS
app.use("/*", cors());

// Health check
app.get("/api/health", (c) => c.json({ status: "ok" }));

// Endpoint to generate a GCS token
app.get("/api/getGCSToken", async (c) => {
  try {
    const credentials = {
      type: process.env.type,
      project_id: process.env.project_id,
      private_key_id: process.env.private_key_id,
      private_key: process.env.private_key?.replace(/\\n/g, "\n"), // important for line breaks
      client_email: process.env.client_email,
      client_id: process.env.client_id,
      auth_uri: process.env.auth_uri,
      token_uri: process.env.token_uri,
      auth_provider_x509_cert_url: process.env.auth_provider_x509_cert_url,
      client_x509_cert_url: process.env.client_x509_cert_url,
    };

    const auth = new GoogleAuth({
      credentials,
      scopes: ["https://www.googleapis.com/auth/devstorage.full_control"],
    });

    const client = await auth.getClient();
    const accessToken = await client.getAccessToken();

    return c.json({ token: accessToken.token });
  } catch (err: any) {
    console.error("Error generating token:", err);
    return c.json({ error: err.message }, 500);
  }
});

// Serve
Bun.serve({
  port: import.meta.env.PORT ?? 3000,
  fetch: app.fetch,
});

Contact:

Drop me a line

Want to work together? Have a question about an article? Feel resentment/hatred toward my person? If you think I can help you with anything drop me an email at tgarnon45@gmail.com or leave a message below and I'll get right back to you.

Contact:

Drop me a line

Want to work together? Have a question about an article? Feel resentment/hatred toward my person? If you think I can help you with anything drop me an email at tgarnon45@gmail.com or leave a message below and I'll get right back to you.

Contact:

Drop me a line

Want to work together? Have a question about an article? Feel resentment/hatred toward my person? If you think I can help you with anything drop me an email at tgarnon45@gmail.com or leave a message below and I'll get right back to you.

Theo Garnon

2025