Result · Authentication Profile

Result Authentication

Authentication

Result secures its APIs with apiKey, http, and oauth2 across 4 declared security schemes, as derived from its OpenAPI definitions. OAuth 2.0 is offered via the authorizationCode flow(s).

CompanyBusiness OperationsSaaSEntrepreneurshipPaymentsMarketingNo-CodeStartupsArtificial IntelligenceBackend as a ServiceModel Context ProtocolAgentsDatabaseAuthenticationStorageServerlessRealtime
Methods: apiKey, http, oauth2 Schemes: 4 OAuth flows: authorizationCode API key in: header

Security Schemes

publishable-anon-key apiKey
· in: header ()
backend-admin-key apiKey
· in: header ()
end-user-session http
scheme: bearer
mcp-oauth oauth2
· flows: authorizationCode

Source

Authentication Profile

result-authentication.yml Raw ↑
generated: '2026-08-13'
method: searched
source: >-
  https://docs.result.dev/sdk/authentication, https://docs.result.dev/guides/security,
  https://docs.result.dev/guides/troubleshooting, and the anonymous RFC 9728/RFC 8414
  metadata at https://api.result.dev/.well-known/oauth-protected-resource
docs:
- https://docs.result.dev/sdk/authentication
- https://docs.result.dev/guides/security
note: >-
  Result publishes no OpenAPI, so this profile is searched from the provider's own
  documentation and from live OAuth discovery metadata rather than derived from
  securitySchemes. There are two distinct authentication planes: credentials that
  authenticate an APPLICATION to its own Result Backend, and an OAuth 2.1 flow that
  authenticates a HUMAN OPERATOR (and their agent) to the Result MCP server.
summary:
  types: [apiKey, http, oauth2]
  api_key_in: [header]
  oauth2_flows: [authorizationCode]
  planes: [backend-credentials, mcp-oauth, end-user-session]
schemes:
- name: publishable-anon-key
  plane: backend-credentials
  type: apiKey
  in: header
  header: Authorization
  format: 'Bearer <publishable key>'
  env_var: NEXT_PUBLIC_BACKEND_ANON_KEY
  public: true
  description: >-
    The publishable client key. Ships in the browser bundle by design — the provider states
    plainly that anyone can read it out of a shipped frontend. It is what @resultdev/sdk
    uses for every application call.
  what_protects_data:
  - Row-level security. Tables created with a user_id uuid column get an owner policy
    scoping rows to the signed-in user; RLS is on by default.
  - Signed-in-only writes. Storage uploads and list() reject anonymous callers.
  - Serverless functions as the trust boundary. AI calls and email sends work with the
    publishable key alone, so anyone holding it can drive spend; the docs direct expensive
    or sensitive operations into a function.
  caveat: >-
    The docs note in passing that an end-user HTTP call carries
    `Authorization: Bearer <publishable key>`, not an x-api-key header — while explicitly
    telling developers not to hand-roll HTTP at all.
- name: backend-admin-key
  plane: backend-credentials
  type: apiKey
  in: header
  env_var: BACKEND_ADMIN_KEY
  public: false
  used_by: '@resultdev/cli'
  description: >-
    Full admin control of the backend — schema, migrations, buckets, realtime channel
    patterns, functions, secrets, payment keys, deployments. Terminal or server-side code
    only.
  prohibitions:
  - Never in client code.
  - Never in a NEXT_PUBLIC_* variable.
  - Never in the browser.
  - Never as a Result-hosting build variable.
- name: end-user-session
  plane: end-user-session
  type: http
  scheme: bearer
  description: >-
    Issued at sign-in and attached by the SDK to every database, storage, function and
    realtime call, which is what makes RLS-scoped tables resolve correctly.
  providers:
  - method: email-password
    operations: [signUp, signInWithPassword, signOut, sendResetPasswordEmail, resetPassword]
    note: >-
      signUp returns a session immediately; email verification is pre-configured off, so
      there is no "check your email" stall.
  - method: oauth
    provider: google
    operation: signInWithOAuth("google")
    note: configured on every backend, no client ID to register, no callback route to build
  - method: oauth
    provider: github
    operation: signInWithOAuth("github")
  discovery_call: getPublicAuthConfig() -> data.oAuthProviders
  token_storage:
    access_token: in memory
    refresh_token: first-party cookie on the application's own origin, written by the SDK
    localstorage: >-
      deliberately empty — the docs state an empty localStorage never means "signed out",
      and that sign-in state must be checked with getCurrentUser(), never by reading browser
      storage
    requires: SDK 0.7.0 or newer for cookie-based session persistence
    hardened_variant: >-
      '@resultdev/sdk/ssr' puts the refresh token in an httpOnly cookie the application's own
      server writes, which browser JavaScript cannot read. The docs name XSS as a
      session-theft hole in the default configuration and call the SSR variant the right
      trade for apps holding something worth stealing.
  session_restore:
    call: getCurrentUser()
    rule: >-
      Must be called on mount. onAuthStateChange() reports changes only and never fires for
      an already-existing session, so it cannot stand in for the restore call.
  flow_control:
    modes: [redirect, popup, auto]
    default: auto
    note: >-
      Google refuses to render inside an iframe, so the SDK detects a framed app and opens a
      popup instead. redirectTo must share an origin with the page starting the sign-in;
      a cross-origin value is refused up front with OAUTH_REDIRECT_CROSS_ORIGIN.
  profiles:
    operations: [getProfile, setProfile]
    fields: [name, avatar_url]
- name: mcp-oauth
  plane: mcp-oauth
  type: oauth2
  flows:
  - flow: authorizationCode
    authorizationUrl: https://api.descope.com/oauth2/v1/apps/authorize
    tokenUrl: https://api.descope.com/oauth2/v1/apps/token
    refreshUrl: https://api.descope.com/oauth2/v1/apps/token
    revocationUrl: https://api.descope.com/oauth2/v1/apps/revoke
    userinfoUrl: https://api.descope.com/oauth2/v1/apps/userinfo
    scopes:
      full-access: Read and write access to the businesses the authenticated account owns.
  issuer: https://api.descope.com/v1/apps/P3HVe6On8gLt3t2puHvHToMFQit2
  jwks_uri: https://api.descope.com/P3HVe6On8gLt3t2puHvHToMFQit2/.well-known/jwks.json
  protected_resource: https://api.result.dev/mcp
  protected_resource_metadata: https://api.result.dev/.well-known/oauth-protected-resource
  dynamic_client_registration: https://api.descope.com/v1/mgmt/inboundapp/app/P3HVe6On8gLt3t2puHvHToMFQit2/register
  pkce: [S256]
  dpop_supported: true
  token_endpoint_auth_methods: [none, client_secret_basic, client_secret_post]
  id_token_signing_alg: [RS256]
  identity_provider: Descope
  sources: [well-known/result-oauth-protected-resource.json, well-known/result-oauth-authorization-server.json]
account_identity:
  note: >-
    The Terms of Service state a Google account is required to sign in to Result itself
    (distinct from the end-user auth an application built on Result offers its own users).
x-evidence:
- url: https://docs.result.dev/sdk/authentication
  status: 200
- url: https://docs.result.dev/guides/security
  status: 200
- url: https://api.result.dev/.well-known/oauth-protected-resource
  status: 200
- url: https://api.descope.com/v1/apps/P3HVe6On8gLt3t2puHvHToMFQit2/.well-known/oauth-authorization-server
  status: 200