Authentifizierung verstehen: Kunden-Token nutzen, den Customer-Context im Resolver prüfen
Authentifizierung verstehen: Kunden-Token nutzen, den Customer-Context im Resolver prüfen
~8 Min. Lesezeit Zuletzt aktualisiert am 9. August 2026
Bevor Kapitel 18 die Favoriten-Mutation absichert, klärt dieses Kapitel die Grundlagen: Wie meldet sich ein Kunde bei GraphQL überhaupt an, und wie erkennt ein Resolver, wer gerade anfragt? Als praktisches, ungefährliches Beispiel dient ein neues Feld is_favorite am Event-Typ, das nur für eingeloggte Kunden sinnvoll befüllt werden kann.
Das Kunden-Token erzeugen
Magento authentifiziert GraphQL-Anfragen über dasselbe Token-System wie die REST-API: eine Mutation generateCustomerToken aus Magento_CustomerGraphQl nimmt E-Mail und Passwort entgegen und liefert ein Bearer-Token zurück.
mutation {
generateCustomerToken(email: "kunde@example.com", password: "geheim123") {
token
}
}Dieses Token wandert bei jeder folgenden Anfrage in den Authorization-Header:
curl -s https://mironsoft.test/graphql \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{"query": "{ customer { email } }"}'Wie der Context daraus entsteht
Magentos GraphQL-Controller liest den Authorization-Header noch vor jedem Resolver-Aufruf aus, validiert das Token und baut daraus die ContextInterface-Instanz, die jeder Resolver als zweiten Parameter erhält (Kapitel 10). Ein fehlendes oder ungültiges Token führt nicht automatisch zu einem Fehler - die Anfrage läuft einfach als Gast weiter, es sei denn, ein einzelnes Feld verlangt selbst eine Authentifizierung.
Beispiel: is_favorite-Feld mit Context-Check
extend type Event {
is_favorite: Boolean!
@resolver(class: "Mironsoft\\Event\\Model\\Resolver\\IsFavorite")
@doc(description: "Whether the current customer has favorited this event")
}<?php
declare(strict_types=1);
namespace Mironsoft\Event\Model\Resolver;
use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Mironsoft\Event\Api\Data\EventInterface;
use Mironsoft\Event\Model\ResourceModel\EventFavorite;
/**
* Resolves the is_favorite field on the Event type. Always false for guests.
*/
class IsFavorite implements ResolverInterface
{
/**
* @param EventFavorite $eventFavoriteResource Resource model for the favorites linkage table
*/
public function __construct(
private readonly EventFavorite $eventFavoriteResource,
) {
}
/**
* Checks whether the current customer has favorited the resolved event.
*
* @param Field $field Resolved GraphQL field configuration
* @param mixed $context Resolver context, carries the customer ID/type
* @param ResolveInfo $info GraphQL resolve tree info
* @param array|null $value Parent Event resolver's value
* @param array|null $args Arguments passed to this field
* @return bool
*/
public function resolve(
Field $field,
$context,
ResolveInfo $info,
?array $value = null,
?array $args = null
): bool {
/** @var EventInterface|null $event */
$event = $value['model'] ?? null;
if ($event === null || !$context->getExtensionAttributes()->getIsCustomer()) {
return false;
}
return $this->eventFavoriteResource->isFavorite(
(int) $context->getUserId(),
(int) $event->getEventId()
);
}
}getExtensionAttributes()->getIsCustomer() ist der zuverlässigste Weg, echte Kunden von Gästen zu unterscheiden - zuverlässiger als eine reine getUserId() > 0-Prüfung, weil getIsCustomer() vom GraphQL-Framework selbst konsistent auf Basis des validierten Tokens gesetzt wird. Für Gäste liefert das Feld einfach false zurück, statt einen Fehler zu werfen - is_favorite ist schließlich auch für Gäste ein fachlich sinnvoller, wahrer Wert ("nein, nicht favorisiert").
Die USER_TYPE_*-Konstanten im Überblick
UserContextInterface::USER_TYPE_GUEST- keine Authentifizierung, kein Token oder abgelaufenes/ungültiges Token.UserContextInterface::USER_TYPE_CUSTOMER- gültiges Kunden-Token, das ist der füraddEventToFavoritesrelevante Fall.UserContextInterface::USER_TYPE_ADMIN- ein Admin-Token statt eines Kunden-Tokens, relevant für Kapitel 23 (ACL).UserContextInterface::USER_TYPE_INTEGRATION- eine Integration (vergleichbar mit einem REST-Access-Token einer Drittanbieter-Anwendung).
Tipp: Für schnelle, wiederholte Tests während der Entwicklung lohnt sich, das Token einmal zu generieren und als Umgebungsvariable oder in der Collection des GraphQL-Clients zu speichern - Kunden-Tokens sind standardmäßig eine gewisse Zeit gültig, ein Neu-Login für jeden einzelnen Testaufruf ist nicht nötig.
Mit dem Verständnis, wie Token, Context und getIsCustomer() zusammenspielen, rüstet Kapitel 18 die Favoriten-Mutation aus Kapitel 16 mit genau diesem Wissen zu einer wirklich geschützten Mutation aus.