Authentication

Identify the caller of your function. When a signed-in user invokes a function from the Koolbase SDK, the runtime injects their identity into ctx.auth.

The ctx.auth object

Every function receives an auth field on its context. Two properties:

ctx.authJSON
{
  "user_id": "bf061caa-b43e-4e18-975a-a4b61f1d030e",
  "is_authenticated": true
}

When no signed-in user is invoking — or when the function is fired by a DB trigger — user_id is null and is_authenticated is false.

Reading the caller

Inside the function, read ctx.auth.user_id to identify who's calling. Reject if absent.

get-profile/index.tsTypeScript
export async function handler(ctx) {
  const userId = ctx.auth?.user_id;
  if (!userId) {
    return {
      error: { code: 'AUTH_REQUIRED', message: 'Sign in required.' },
      status: 401,
    };
  }

  const result = await ctx.db.find('profiles', { user_id: userId }, 1);
  return { profile: result.records?.[0] ?? null };
}
get_profile/index.dartDart
Future<Map<String, dynamic>> handler(Map<String, dynamic> ctx) async {
  final auth = ctx['auth'] as Map<String, dynamic>?;
  final userId = auth?['user_id'] as String?;

  if (userId == null) {
    return {
      'error': {'code': 'AUTH_REQUIRED', 'message': 'Sign in required.'},
      'status': 401,
    };
  }

  final db = ctx['db'] as Map<String, dynamic>;
  final result = await (db['find'] as Function)('profiles', {'user_id': userId}, 1);
  final records = (result['records'] as List?) ?? [];
  return {'profile': records.isEmpty ? null : records.first};
}

Public functions

Some functions are designed to be called without a signed-in user — sign-up flows, password reset, anonymous reads. Skip the auth check and proceed:

track-event/index.tsTypeScript
export async function handler(ctx) {
  // No auth check — anyone can call this.
  await ctx.db.insert('events', {
    name: ctx.request.body.event,
    timestamp: new Date().toISOString(),
  });
  return { ok: true };
}

A function can also do both — branch on ctx.auth.is_authenticated when authenticated callers get a richer response than anonymous ones.

Invoking from the SDK

When a user is signed in via Koolbase.auth, the SDK forwards their access token on every Koolbase.functions.invoke() call. No extra arguments needed.

lib/profile_service.dartDart
await Koolbase.auth.signInWithEmail(email, password);

final result = await Koolbase.functions.invoke('get-profile');
// ctx.auth.user_id is populated inside the function.
src/profile-service.tsTypeScript
await Koolbase.auth.signIn(email, password);

const result = await Koolbase.functions.invoke('get-profile');
// ctx.auth.user_id is populated inside the function.

Token refresh is transparent

The SDK reads the current access token fresh on every invoke. When the auth client refreshes the token in the background, the next invoke automatically uses the new one — no client-side wiring required.

Direct REST invoke

When calling the REST endpoint directly, attach the user's access token as a Bearer header alongside the project's API key:

curl -X POST https://api.koolbase.com/v1/sdk/functions/get-profile \
  -H "Content-Type: application/json" \
  -H "x-api-key: pk_live_your_key" \
  -H "Authorization: Bearer <user_access_token>" \
  -d '{"body": {}}'

Without the Authorization header, the request is treated as unauthenticated and ctx.auth.is_authenticated resolves to false.

SDK compatibility

ctx.auth is populated automatically when calling from these SDK versions or later:

Flutter
koolbase_flutter2.8.0+
React Native
@techfinityedge/koolbase-react-native1.8.0+

Older SDK versions

Earlier SDK versions don't forward the access token. Functions invoked from those clients see ctx.auth.is_authenticated as false even when the user is signed in. Upgrade the SDK to enable authenticated invocations.