Skip to content

Host lookup by iss crashes under generateId: "serial" when host uses a non-numeric ID #37

Description

@n1vedhar1

Using generateId: "serial" (integer PKs) and allowDynamicHostRegistration: true, any external agent that self-registers crashes the request instead of succeeding or getting a clean error.

findHostByIdOrKid looks up the host by the JWT's iss claim directly against id:

async function findHostByIdOrKid(adapter, iss) {
  return await adapter.findOne({
    model: TABLE.host,
    where: [{ field: "id", value: iss }]
  }) ?? await adapter.findOne({
    model: TABLE.host,
    where: [{ field: "kid", value: iss }]
  });
}

Under generateId: "serial", better-auth's core adapter coerces any id-referencing filter value with Number(value) before it reaches Prisma, with no check on whether that produces a real number:

const useNumberId = options.advanced?.database?.generateId === "serial";
...
if (defaultFieldName === "id" || fieldAttr.references?.field === "id") {
  newValue = Number(newValue);
}

@auth/agent's client defaults a host JWT's iss to a JWK thumbprint, a non-numeric string by design. Number(thumbprint) is NaN, Prisma rejects it as an invalid Int filter, and the request throws before it ever reaches the kid fallback in findHostByIdOrKid. That fallback only runs if the first lookup resolves to null, not if it throws.

Environment

  • @better-auth/agent-auth: 0.4.5 (same code in 0.6.2, unchanged)
  • better-auth / @better-auth/core / @better-auth/prisma-adapter: 1.5.6
  • @auth/agent (client): 0.5.1
  • PostgreSQL via Prisma, advanced.database.generateId: "serial"

Reproduction

  1. agentAuth({ modes: ["autonomous"], allowDynamicHostRegistration: true, ... }) on a betterAuth() instance with generateId: "serial".
  2. External agent discovers the provider (works fine) and calls client.connectAgent({ provider, mode: "autonomous", ... }).
  3. connectAgent() signs a host JWT with the default iss and POSTs to /agent/register.

Current vs. expected

Current, 500:

PrismaClientValidationError:
Invalid `prisma.agentHost.findFirst()` invocation:
{ where: { id: { equals: Int | IntFieldRefInput, ... } }, select: undefined }
Argument `id` is missing.

Expected: registration succeeds, or fails with a normal auth error, not an unhandled adapter exception. At minimum the kid fallback in findHostByIdOrKid should actually be reachable for a non-numeric iss.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions