Zum Inhalt springen
BeeuniBeeuni
Deutsch
Esc
↑↓navigieren↵öffnen⌘Jvorschau
Auf dieser Seite

Mit Beeuni anmelden

Sichere deine eigene App mit einer einzigen Route über die Beeuni-Identität ab und handle über das SDK als angemeldeter Nutzer.

„Mit Beeuni anmelden“ macht Beeuni zum Identitätsanbieter für eine App, die du betreibst: ein Dashboard, ein internes Tool oder ein auf Beeuni aufgebautes Branchenprodukt. Deine Nutzer melden sich mit ihrem Beeuni-Konto an, dein Server weiß, wer sie sind, und jeder Beeuni-Aufruf deiner App wird als dieser Nutzer mit dessen Rollenzuweisungen ausgeführt. Der gesamte Ablauf liegt in @beeuni/sdk. Deine App speichert nie ein Beeuni-Token im Browser.

Es handelt sich um standardmäßiges OAuth 2.1 (Autorisierungscode + PKCE), bereitgestellt von der Beeuni API unter api.beeuni.ai.

1. Registriere deine App

Gehe zu Account → Tokens → OAuth apps → Register app oder rufe das SDK auf:

const app = await beeuni.iam.oauthClients.create(accountId, {
  name: 'Dashboards',
  client_type: 'confidential',            // 'public' for a browser/native app (PKCE only, no secret)
  redirect_uris: ['https://dashboards.example.com/api/beeuni/auth/callback'],
  scopes: ['profile', 'email', 'beeuni'],
});
// app.client_id, app.client_secret (shown once)

Die Registrierung erfordert token.create für das Konto. Redirect-URIs werden Byte für Byte verglichen; https ist erforderlich, außer auf localhost.

Scope Gewährt der App
profile Die ID, E-Mail-Adresse und Kontomitgliedschaften des Nutzers (GET /v1/accounts/me).
email Die E-Mail-Adresse (ein Alias für OIDC-kompatible Clients).
beeuni Handeln als Nutzer über die gesamte Beeuni API — Projekte, Sitzungen, Dateien, IAM-Prüfungen. Ohne diesen Scope dient das Token nur zur Identifizierung.

2. Binde den Handler ein

// lib/beeuni-auth.ts
import { createBeeuniAuth } from '@beeuni/sdk/server';

export const auth = createBeeuniAuth({
  backendUrl: 'https://api.beeuni.ai/v1',
  clientId: process.env.BEEUNI_OAUTH_CLIENT_ID!,
  clientSecret: process.env.BEEUNI_OAUTH_CLIENT_SECRET,   // omit for a public client
  redirectUri: 'https://dashboards.example.com/api/beeuni/auth/callback',
  cookieSecret: process.env.BEEUNI_AUTH_COOKIE_SECRET!,   // ≥ 32 chars; encrypts the session cookie
});
// app/api/beeuni/auth/[...beeuni]/route.ts  (Next.js App Router)
import { auth } from '@/lib/beeuni-auth';
const handle = (request: Request) => auth.handler(request);
export { handle as GET, handle as POST };

Der Handler bedient jede Route unter basePath (abgeleitet von der Redirect- URI — oben /api/beeuni/auth):

Pfad Funktion
/signin?return_to=/path Startet die Anmeldung (PKCE S256 + State in einem 10-Minuten-Cookie) und leitet zu Beeuni weiter.
/callback Tauscht den Code aus, setzt das verschlüsselte Sitzungscookie HttpOnly und leitet zu return_to weiter.
/refresh?return_to= Rotiert das Tokenpaar und leitet weiter. Wird von requireViewer verwendet.
/signout?return_to= Widerruft das Refresh-Token bei Beeuni und löscht das Cookie.
/me Der Betrachter als JSON oder 401. Aktualisiert direkt, wenn das Zugriffstoken abgelaufen ist.
/proxy/* Leitet als Betrachter an die Beeuni API weiter. Das backendUrl des Browser-SDKs.

return_to ist immer auf einen Pfad derselben Origin beschränkt.

3. Schütze Seiten und handle als Nutzer

// middleware.ts — every page needs a viewer
import { auth } from '@/lib/beeuni-auth';

export async function middleware(request: Request) {
  const gate = await auth.requireViewer(request);
  if (gate.response) return gate.response;   // 302 → /refresh or /signin
}
export const config = { matcher: ['/((?!api/beeuni/auth|_next).*)'] };
// a server component / route handler
const viewer = await auth.viewer(request);       // { userId, email, accounts, scopes, token, expiresAt } | null
const beeuni = await auth.beeuni(request);       // request-scoped client acting as the viewer
const projects = await beeuni.projects.list();
const allowed = await beeuni.iam.can(accountId, viewer!.userId, { action: 'project.write', resourceType: 'project', resourceId });

viewer() ist schreibgeschützt und verbraucht nie das einmalig verwendbare Refresh-Token; verwende requireViewer() in der Middleware, damit eine Seite für einen Nutzer, dessen Refresh-Token noch gültig ist, nie im abgemeldeten Zustand gerendert wird.

4. Der Browser

import { createBeeuni } from '@beeuni/sdk';
import { SignInWithBeeuni, useBeeuniViewer } from '@beeuni/sdk/react';

const beeuni = createBeeuni(auth.clientConfig());   // backendUrl = '/api/beeuni/auth/proxy'

function Header() {
  const { status, viewer } = useBeeuniViewer();
  if (status === 'signed-in') return <span>{viewer.email}</span>;
  return <SignInWithBeeuni className="button" />;
}

Der Browser-Client sendet einen Sentinel-Bearer; /proxy ersetzt ihn auf dem Server durch das echte Token des Betrachters. useSession, beeuni.project(id).sessions.* und alle anderen SDK-Aufrufe funktionieren darüber unverändert.

Was der Nutzer sieht

Beim ersten Mal zeigt Beeuni einen Zustimmungsbildschirm mit dem Namen deiner App und den Scopes. Beeuni merkt sich die Entscheidung pro Nutzer und App, sodass spätere Anmeldungen direkt zurückleiten. Der Widerruf einer App löscht jedes von ihr ausgestellte Token.

Discovery

GET https://api.beeuni.ai/.well-known/oauth-authorization-server (auch unter /v1/oauth/.well-known/…) veröffentlicht die Endpunkte für einen generischen OAuth- Client. Das SDK benötigt dies nicht — es leitet jeden Endpunkt aus backendUrl ab.

Anmeldetokens für Apps

Code in einer von Beeuni gehosteten App und in den von ihr genutzten Apps akzeptiert eine zweite Art von Token: ein kurzes ES256-JWT, das Beeuni für eine einzelne App ausstellt. Kein OAuth-Ablauf, keine Weiterleitung, kein Client-Secret.

Wert
Aussteller <API origin>/v1/projects/<projectId>, einer pro Projekt
Discovery <issuer>/.well-known/openid-configuration und <issuer>/jwks.json, öffentlich
Zielgruppe Die ID der App, für die das Token bestimmt ist
Gültigkeitsdauer 15 Minuten
Claims sub, email, name, picture, groups, group_ids, role, account_id, project_id; das Token eines Agenten enthält zusätzlich kind: "agent" und hat keine Gruppen oder Rolle

Jede App enthält die Werte zur Prüfung ihrer Tokens: app.auth.issuer, app.auth.audience, app.auth.jwks_uri.

import { beeuniToken, beeuniBinding, verifyBeeuniToken, requireBeeuniMember } from '@beeuni/sdk';

// In the App's browser code: a token fetcher for this App, or an App it uses.
const forThisApp = beeuniToken();
const forDb = beeuniToken({ audience: 'db' });
const db = beeuniBinding('db');   // { url: '<origin>/_beeuni/apps/db', token: forDb }

// On a server that receives the token:
const member = await verifyBeeuniToken(bearer, {
  issuer: app.auth.issuer,
  audience: app.auth.audience,
  jwks: app.auth.jwks_uri,
});
requireBeeuniMember(member, { roles: ['owner', 'admin'] });

In einer Server-App fügt Beeuni BEEUNI_AUTH_ISSUER (den Projektaussteller), BEEUNI_AUTH_AUDIENCE (die eigene ID der App) und BEEUNI_AUTH_JWKS (den Schlüsselsatz des Projekts als data:-URI) ein, sodass verifyBeeuniToken(bearer) keine Optionen benötigt. Setze BEEUNI_AUTH_* nicht selbst: Das Präfix BEEUNI_ ist reserviert und beeuni validate weist es zurück.

verifyBeeuniToken lehnt ein Token ab, wenn keine Zielgruppe gesetzt ist (die Option oder BEEUNI_AUTH_AUDIENCE): Ein Projektschlüssel signiert die Tokens jeder App im Projekt, daher verhindert aud die Annahme eines Tokens einer anderen App. Übergib audience: false nur, um ein Token für eine beliebige App des Projekts zu akzeptieren.

beeuniToken liest GET /_beeuni/token?audience=<slug or id> auf der eigenen Origin der App. Die Zielgruppe ist die App selbst (Standard) oder eine von ihr genutzte App (beeuni apps link <app> --uses <other>); jede andere führt zu 403 app_not_linked. Ein Mitglied, ein Skript oder ein Agent stellt stattdessen eines über die API aus: beeuni.project(projectId).apps.token(appId) oder beeuni apps token <app>. Der vollständige Vertrag, die Einbindung der Bindings und die Einrichtung des Convex-Backends: SDK → Apps und Apps → Von einer App genutzte Apps.

War diese Seite hilfreich?