Understand legacy mobile sign-in and the planned backend-mediated member sign-in flow.
The GOFA Lessons and WebView Flutter SDKs sign a member in to Firebase before opening GOFA features. A Firebase custom token is used once to sign in; the resulting Firebase ID token represents the signed-in member on protected user routes. A ClientToken is a separate backend credential for privileged client API operations. It is not an SDK member sign-in token.
Do not put a client secret in a new mobile integration
Existing Lessons and WebView releases accept clientId and clientSecret in
the host app. Some older guides show the secret in Dart code or a
--dart-define build argument. Both approaches place it in the distributed
app, where it can be recovered. Build-time configuration, obfuscation, and
removing the value from source control do not make a mobile client secret
confidential. These examples document compatibility for existing deployments;
contact GOFA before starting a new member sign-in integration.
clientSecret: Continue its current sign-in path
while planning a coordinated migration with GOFA. Treat an app-embedded
secret as exposed, and account for older app versions before rotation./api/client administration: Use
Client tokens from a
trusted backend. Do not send the client secret or ClientToken to the app.Preview contract — not yet released
The external_user grant and SDK customTokenProvider shown here are under
development. This section is for planning and integration review. Do not
assume these calls work in production or switch an existing app until GOFA
announces the supported server and SDK versions, provisions the dedicated
key, and enables the client's API module and SSO setting.
The partner app continues to authenticate its member in the partner's own system. The partner backend then requests a GOFA Firebase custom token for that same member:
POST /api/auth/custom-token with a dedicated
external_user_sso key stored in its secret manager. The request has
grantType: "external_user" and externalUserId set to the stable member ID.
The key identifies the GOFA client; do not send clientId, roles, claims,
email, or a client secret in this request.customToken to that authenticated
app session over HTTPS. The app's SDK token provider supplies a fresh token
when GOFA needs to sign in or open a WebView. Do not log or persist the token.The partner backend must obtain the GOFA SSO key from server-only storage. The authenticated session and member lookup below represent the partner's existing backend authentication; they are not GOFA endpoints.
const member = await requireAuthenticatedMember(request);
const gofaSsoKey = await getGofaSsoKeyFromSecretManager();
const response = await fetch('https://www.gofa.app/api/auth/custom-token', {
method: 'POST',
headers: {
Authorization: `Bearer ${gofaSsoKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
grantType: 'external_user',
externalUserId: member.stableId,
}),
});
if (!response.ok) throw new Error(`GOFA sign-in failed: ${response.status}`);
const { customToken } = await response.json();
return Response.json(
{ customToken },
{ headers: { 'Cache-Control': 'no-store' } },
);Use https://www.uat.gofa.app/api/auth/custom-token and a separate UAT key
while testing.
Never reuse the SSO key as a Commercial API key or a client secret for
POST /api/client/token.
fetchGofaCustomToken() calls the partner backend with the member's
authenticated app session. The clientUserId must match the stable ID the
backend sends as externalUserId.
await WebViewSdkManager().init(
clientId: 'your-client-id',
clientUserId: stableMemberId,
customTokenProvider: () async => partnerBackend.fetchGofaCustomToken(),
environment: Environment.PRD,
);For GOFA Lessons, use the same provider with an explicit member ID in params:
await LessonSdkManager().init(
environment: Environment.PRD,
params: {
'clientId': 'your-client-id',
'clientUserId': stableMemberId,
},
customTokenProvider: () async => partnerBackend.fetchGofaCustomToken(),
);In provider mode, omit clientSecret; the SDK accepts exactly one token source.
The GOFA backend key must never be included in Flutter code, build arguments,
assets, URLs, or client logs.
For the existing SDK setup and MSK WebView handoff, see WebView getting started, Lessons code setup, and MSK authentication.