メインコンテンツまでスキップ
非公開のページ
このページは非公開です。 検索対象外となり、このページのリンクに直接アクセスできるユーザーのみに公開されます。

Troubleshoot Extend App UI

Last updated on April 28, 2026

Overview

This page covers the issues you are most likely to hit when your Extend App UI calls an Extend Service Extension or Event Handler from the AccelByte Gaming Services (AGS) Admin Portal. The most common one by far is authentication: if your service only reads the Authorization header, requests coming from the Admin Portal fail with a 401 because they are authenticated via an access_token cookie instead.

Permission errors when calling your Extend service from the Admin Portal

Symptom

Calls from your App UI to your Extend service fail with HTTP 401 and a message like authorization header is missing. The same endpoint works fine when you call it directly from Swagger, Postman, or a local test with a Bearer token.

Cause

When the Admin Portal embeds your App UI, the browser authenticates using a cookie named access_token, not an Authorization header. This is how gRPC-Gateway handles browser-based auth for services that expose REST endpoints on top of gRPC. If your service's gRPC auth interceptor only inspects the Authorization header, every cookie-authenticated request from the Admin Portal is rejected.

Local development hits this problem too. devProxyPlugin does not convert the cookie into an Authorization header; it only rewrites the Referer so requests look like they came from the expected namespace subdomain. The cookie is forwarded to your service unchanged. See devProxyPlugin for what the plugin does and does not touch. The fix has to happen on the service side: your interceptor has to accept the cookie directly.

Fix

Before applying this fix, update your Extend SDK to the latest version. The required cookie-handling APIs may not be present in older releases.

Update your gRPC auth interceptor to fall back to the cookie metadata when the Authorization header is missing. Pull the access_token=... value out of the cookie string and validate it the same way you validate a Bearer token. Apply the same fallback to any helper that reads the namespace, user ID, or username from the token.

The Go example below shows the pattern applied to a service scaffolded from the Extend Tournament System template. The same logic applies to any Extend service regardless of language: if Authorization is missing, pull access_token out of the cookie metadata. The exact file paths, struct names, and helper functions in this snippet will vary depending on your Extend implementation—adapt them to match your project structure.

Use net/http to parse the cookie instead of splitting the header by hand. Wrapping each cookie metadata entry in a minimal http.Request lets you reuse the standard library's cookie parsing and avoid edge cases around quoting, spacing, and multiple cookie headers.

// pkg/common/auth_interceptors.go

// extractTokenFromCookieMetadata parses the "cookie" metadata key and
// returns the access_token value if present.
func extractTokenFromCookieMetadata(meta metadata.MD) string {
for _, cookieHeader := range meta.Get("cookie") {
req := &http.Request{Header: http.Header{"Cookie": {cookieHeader}}}
if cookie, err := req.Cookie("access_token"); err == nil {
return cookie.Value
}
}
return ""
}

func (t *TournamentAuthInterceptor) CheckTournamentPermission(
ctx context.Context,
requiredPermission string,
namespace string,
) error {
meta, ok := metadata.FromIncomingContext(ctx)
if !ok {
return status.Error(codes.Unauthenticated, "missing metadata")
}

// Existing checks for Authorization header and service tokens go here.
// ...

// Check for token in cookies (browser-based authentication via gRPC-Gateway).
if token := extractTokenFromCookieMetadata(meta); token != "" {
return t.validateToken(ctx, token, requiredPermission, namespace)
}

return status.Error(codes.Unauthenticated, "authorization header or cookie is missing")
}

Apply the same fallback to any context helper that extracts claims from the token. The pattern is always: try Authorization first, then fall back to extractTokenFromCookieMetadata(meta). For example, GetContextUserID, GetContextUsername, and GetContextNamespace all reuse the same lookup before decoding the JWT and returning the relevant claim.

Verify the fix

  1. Redeploy your Extend service.
  2. Open your App UI. You can do this from the Admin Portal (go to Extend > My Extend Apps > App UI, then click Open UI on your app's row) or from your local dev server at http://localhost:5173 after running npm run dev.
  3. Trigger a request that previously returned 401. It should now succeed.
  4. Check your service logs to confirm the request was authenticated via the cookie path and not rejected at the interceptor.

403 insufficient-permission error when fetching namespace context

注記

This issue only applies to AGS Private Cloud deployments. On AGS Shared Cloud, studio and game admins do not have access to the Publisher namespace, so this conflict does not arise.

Symptom

During local validation, your Extend service logs an error like:

failed to fetch namespace context. [GET /basic/v1/admin/namespaces/{namespace}/context][403] getNamespaceContextForbidden {"devStackTrace":"require permission: Permission(resource=ADMIN:NAMESPACE:{namespace}:NAMESPACE, action=2)","errorCode":20013,"errorMessage":"insufficient permission","requiredPermission":{"action":2,"resource":"ADMIN:NAMESPACE:{namespace}:NAMESPACE"}}

Cause

Your Extend service is calling the Publisher namespace instead of the game namespace it is deployed in. Under normal circumstances, your Extend service should only call the game namespace it is deployed in. Calling the Publisher namespace is only appropriate if your service explicitly requires it as part of its design.

On Shared Cloud, studio and game admins do not have access to the Publisher namespace, so this error will not surface there.

Fix

Review your Extend service's namespace logic and confirm it targets only the game namespace it belongs to. Unless your service explicitly requires Publisher namespace access as part of its design, every namespace-scoped API call should use the game namespace, not the Publisher namespace.