WebsitePlatform Login

Identity Forwarding

Delegierte Authentifizierung zu Third-Party-Systemen mit meinGPT JWT

JWT Identity Forwarding

Mit JWT Identity Forwarding gibt meinGPT einen signierten JSON Web Token an Dritt-Systeme weiter, damit diese den aktuellen Nutzer und die Organisation sicher identifizieren können.

Dieses Muster wird in zwei Bereichen genutzt:

  • Custom MCP Server — Token im HTTP-Header X-meinGPT-JWT
  • Custom AI Apps (iframe) — Token im URL-Hash-Fragment

JWT-Tokens werden nur für Nutzer mit der Rolle Admin oder Mitglied ausgestellt. Viewer erhalten keine Tokens.

Token-Details

EigenschaftWert
AlgorithmusRS256 (RSA + SHA-256)
Gültigkeit1 Stunde
HeaderEnthält kid (Key-ID) für Key-Rotation
IssuerDie Origin Deiner meinGPT-Instanz (z. B. https://app.meingpt.com)

Claims-Referenz

ClaimTypBeschreibung
issstringIssuer — die Plattform-Origin (z. B. https://app.meingpt.com)
substringSubject — die User-ID
audstringAudience — die Organization-ID
expnumberAblaufzeit (Unix-Timestamp, 1 Stunde ab Ausstellung)
iatnumberAusstellungszeitpunkt (Unix-Timestamp)
jtistringEindeutige Token-ID (UUID, ändert sich bei jeder Ausstellung)
emailstringE-Mail-Adresse des Nutzers
usernamestringAnzeigename des Nutzers
organizationNamestringName der Organisation
rolestring"admin" oder "member"
teamsarrayTeams des Nutzers — jeder Eintrag hat id und name

Beispiel-Payload:

{
  "iss": "https://app.meingpt.com",
  "sub": "clx1234567890",
  "aud": "clx0987654321",
  "exp": 1719504000,
  "iat": 1719500400,
  "jti": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "email": "max@example.com",
  "username": "Max Mustermann",
  "organizationName": "Acme Corp",
  "role": "admin",
  "teams": [
    { "id": "clxteam001", "name": "Engineering" }
  ]
}

Verifikation über JWKS

Öffentliche Schlüssel werden pro Organisation bereitgestellt:

https://app.meingpt.com/api/custom-apps/v1/jwks/{organizationId}
import { createRemoteJWKSet, jwtVerify } from 'jose';

const JWKS = createRemoteJWKSet(
  new URL('https://app.meingpt.com/api/custom-apps/v1/jwks/<organizationId>')
);

async function verifyMeinGptJwt(token: string) {
  const { payload } = await jwtVerify(token, JWKS, {
    issuer: 'https://app.meingpt.com',
    audience: '<organizationId>',
  });

  console.log('User:', payload.email);
  console.log('Role:', payload.role);
  return payload;
}
import jwt
from jwt import PyJWKClient

JWKS_URL = "https://app.meingpt.com/api/custom-apps/v1/jwks/<organizationId>"
jwks_client = PyJWKClient(JWKS_URL)

def verify_meingpt_jwt(token: str) -> dict:
    signing_key = jwks_client.get_signing_key_from_jwt(token)
    payload = jwt.decode(
        token,
        signing_key.key,
        algorithms=["RS256"],
        issuer="https://app.meingpt.com",
        audience="<organizationId>",
    )
    return payload

Transport: Custom MCP Server

Wenn JWT Identity Forwarding für einen MCP-Server aktiviert ist, enthält jeder Request:

X-meinGPT-JWT: eyJhbGciOiJSUzI1NiIs...

Tokens werden innerhalb einer Chat-Session gecacht und 30 Sekunden vor Ablauf automatisch erneuert. Dein Server muss keine neuen Tokens anfragen — jeder MCP-Call kommt mit einem gültigen Token an.

So aktivierst Du es

Navigiere zur Konfiguration Deines Assistenten und öffne den Bereich Tools.

Füge einen neuen Custom MCP Server hinzu oder bearbeite einen bestehenden.

Schalte JWT Authentication ein. Der Hinweistext bestätigt: „Sends a signed meinGPT JWT in header X-meinGPT-JWT."

Token auf Deinem Server lesen

Extrahiere den Header und verifiziere ihn:

// Express-Middleware-Beispiel
import { createRemoteJWKSet, jwtVerify } from 'jose';

const JWKS = createRemoteJWKSet(
  new URL('https://app.meingpt.com/api/custom-apps/v1/jwks/<organizationId>')
);

app.use(async (req, res, next) => {
  const token = req.headers['x-meingpt-jwt'];
  if (!token) return res.status(401).json({ error: 'Missing JWT' });

  try {
    const { payload } = await jwtVerify(token, JWKS, {
      issuer: 'https://app.meingpt.com',
      audience: '<organizationId>',
    });
    req.user = payload;
    next();
  } catch {
    res.status(401).json({ error: 'Invalid token' });
  }
});

Custom-Header mit JWT-Platzhalter

Alternativ zum Schalter kannst Du den Platzhalter {{MEINGPT_JWT}} in jedem Custom-Header-Wert verwenden. Das ist nützlich, wenn Dein Server den Token in einem anderen Header erwartet (z. B. Authorization: Bearer {{MEINGPT_JWT}}). Der Platzhalter wird zur Laufzeit durch den signierten JWT ersetzt.


Transport: Custom AI Apps (iframe)

Für eingebettete AI Apps wird der Token beim initialen Laden im URL-Hash-Fragment übergeben und per postMessage erneuert.

Initialer Token

Wenn meinGPT Deine App im iframe lädt, sieht die URL so aus:

https://deine-app.example.com/path#token=eyJhbGciOiJSUzI1NiIs...

So extrahierst Du ihn im Frontend:

function getInitialToken() {
  const params = new URLSearchParams(window.location.hash.slice(1));
  return params.get('token');
}

Token-Refresh per postMessage

Tokens laufen nach 1 Stunde ab. Deine App kann jederzeit per postMessage einen neuen Token anfragen:

1. Neuen Token anfragen — sende an das Parent-Fenster:

window.parent.postMessage({ type: 'MEINGPT_TOKEN_REFRESH' }, '*');

2. Auf die Antwort lauschen:

window.addEventListener('message', (event) => {
  // Origin validieren
  if (event.origin !== 'https://app.meingpt.com') return;

  if (event.data.type === 'MEINGPT_TOKEN_RESPONSE') {
    // Erfolg — neuen Token speichern
    const { token, expiresAt } = event.data;
    setToken(token);
    scheduleRefresh(new Date(expiresAt));
  }

  if (event.data.type === 'MEINGPT_TOKEN_ERROR') {
    // Token-Refresh fehlgeschlagen
    console.error('Token refresh failed:', event.data.error);
  }
});

Nachrichtentypen:

NachrichtRichtungFelderBeschreibung
MEINGPT_TOKEN_REFRESHApp → meinGPT—Neuen Token anfragen
MEINGPT_TOKEN_RESPONSEmeinGPT → Apptoken, expiresAtNeuer signierter JWT + Ablaufzeitpunkt
MEINGPT_TOKEN_ERRORmeinGPT → ApperrorFehlermeldung als String

meinGPT validiert die postMessage-Origin gegen Deine konfigurierte Embed-URL. Nachrichten von unbekannten Origins werden ignoriert.

Vollständiges Lifecycle-Beispiel

let currentToken = null;
let refreshTimer = null;

// 1. Initialen Token aus dem URL-Hash lesen
currentToken = new URLSearchParams(window.location.hash.slice(1)).get('token');

// 2. Refresh planen (z. B. 5 Minuten vor Ablauf)
function scheduleRefresh(expiresAt) {
  clearTimeout(refreshTimer);
  const ms = new Date(expiresAt).getTime() - Date.now() - 5 * 60 * 1000;
  if (ms > 0) {
    refreshTimer = setTimeout(requestRefresh, ms);
  }
}

// 3. Refresh per postMessage anfragen
function requestRefresh() {
  window.parent.postMessage({ type: 'MEINGPT_TOKEN_REFRESH' }, '*');
}

// 4. Antwort verarbeiten
window.addEventListener('message', (event) => {
  if (event.origin !== 'https://app.meingpt.com') return;

  if (event.data.type === 'MEINGPT_TOKEN_RESPONSE') {
    currentToken = event.data.token;
    scheduleRefresh(event.data.expiresAt);
  }
});

Sicherheitshinweise

Verifiziere immer die JWT-Signatur über den JWKS-Endpunkt. Vertraue dem Token-Payload niemals ohne kryptografische Prüfung.

  • Signatur verifizieren — nutze den JWKS-Endpunkt, dekodiere nicht einfach nur den Payload
  • exp prüfen — lehne abgelaufene Tokens ab
  • aud validieren — stelle sicher, dass die Audience mit Deiner erwarteten Organization-ID übereinstimmt
  • HTTPS verwenden — Dein Endpunkt muss TLS nutzen, um den Token bei der Übertragung zu schützen
  • Tokens nicht loggen — JWTs enthalten personenbezogene Daten (E-Mail, Name); vermeide es, sie in Anwendungslogs zu schreiben
  • iframe-Apps: event.origin validieren — akzeptiere postMessage-Events nur von der Origin Deiner meinGPT-Instanz

Weiterführend

Auf dieser Seite