Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

ACL und Berechtigungen für eigene GraphQL-Endpunkte

ACL und Berechtigungen für eigene GraphQL-Endpunkte

~8 Min. Lesezeit Zuletzt aktualisiert am 9. August 2026

Kapitel 1 hat es bereits angerissen: GraphQL übernimmt das ACL-Modell aus webapi.xml nicht automatisch. Die bisherigen Zugriffsprüfungen (Kapitel 17-18) betrafen ausschließlich Kunden - Gast vs. eingeloggt. Dieses letzte Kapitel von Block 6 zeigt den selteneren, aber praxisrelevanten Fall: einen GraphQL-Endpunkt, der nur für Admin-Nutzer mit einer bestimmten ACL-Berechtigung zugänglich sein soll.

Ein Admin-only-Auswertungsfeld

Ein realistischer Anwendungsfall: eine interne Auswertung, wie oft jede Veranstaltung favorisiert wurde - fachlich sinnvoll für ein Backoffice-Dashboard, aber nichts, was jeder anonyme Storefront-Client sehen soll.

app/code/Mironsoft/Event/etc/schema.graphqls
type Query {
    eventFavoritesReport: [EventFavoritesReportItem]
        @resolver(class: "Mironsoft\\Event\\Model\\Resolver\\EventFavoritesReport")
        @doc(description: "Admin-only report of favorite counts per event")
}

type EventFavoritesReportItem @doc(description: "One row of the favorites report") {
    event_id: Int!
    title: String!
    favorite_count: Int!
}

Die ACL-Ressource deklarieren

app/code/Mironsoft/Event/etc/acl.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Acl/etc/acl.xsd">
    <acl>
        <resources>
            <resource id="Magento_Backend::admin">
                <resource id="Mironsoft_Event::event" title="Event Management">
                    <resource id="Mironsoft_Event::event_report"
                              title="View Favorites Report"/>
                </resource>
            </resource>
        </resources>
    </acl>
</config>

Diese Deklaration folgt exakt derselben ACL-Konvention wie jedes Admin-Grid der Admin-Grids-&-Formulare-Serie - GraphQL bringt hier kein eigenes Berechtigungssystem mit, sondern nutzt Magentos reguläres, für den Adminbereich gedachtes ACL komplett wieder.

Den Resolver gegen das Admin-Token prüfen

app/code/Mironsoft/Event/Model/Resolver/EventFavoritesReport.php
<?php

declare(strict_types=1);

namespace Mironsoft\Event\Model\Resolver;

use Magento\Authorization\Model\UserContextInterface;
use Magento\Framework\Authorization\AuthorizationInterface;
use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;

/**
 * Resolves the eventFavoritesReport query field, restricted to admin users
 * holding the Mironsoft_Event::event_report ACL resource.
 */
class EventFavoritesReport implements ResolverInterface
{
    private const ACL_RESOURCE = 'Mironsoft_Event::event_report';

    /**
     * @param AuthorizationInterface $authorization Checks ACL resources for the current admin user
     */
    public function __construct(
        private readonly AuthorizationInterface $authorization,
    ) {
    }

    /**
     * Returns favorite counts per event, restricted to authorized admin users.
     *
     * @param Field $field Resolved GraphQL field configuration
     * @param mixed $context Resolver context, expected to carry an admin token
     * @param ResolveInfo $info GraphQL resolve tree info
     * @param array|null $value Parent resolver's value, unused for a top-level field
     * @param array|null $args Arguments passed to this field
     * @return array<int, array<string, mixed>>
     * @throws GraphQlAuthorizationException
     */
    public function resolve(
        Field $field,
        $context,
        ResolveInfo $info,
        ?array $value = null,
        ?array $args = null
    ): array {
        if ($context->getUserType() !== UserContextInterface::USER_TYPE_ADMIN
            || !$this->authorization->isAllowed(self::ACL_RESOURCE)
        ) {
            throw new GraphQlAuthorizationException(
                __('You are not authorized to view the favorites report.')
            );
        }

        // ... Report-Daten laden und als EventFavoritesReportItem[] zurueckgeben
        return [];
    }
}

AuthorizationInterface::isAllowed() ist dieselbe Klasse, die auch reguläre Admin-Controller und Menüpunkte (acl.xml in der Admin-Grids-&-Formulare-Serie) für ihre Zugriffsprüfung nutzen - GraphQL greift hier auf exakt dieselbe Infrastruktur zu, statt eine eigene zu erfinden.

Admin-Token statt Kunden-Token

Der Aufruf einer solchen Query braucht ein Admin-Token statt eines Kunden-Tokens im Authorization-Header - erzeugt z. B. über eine Magento-Integration oder den regulären Admin-Login-Endpunkt der REST-API. Für die Storefront-typischen Kunden-Mutations aus Kapitel 16-18 ist dieser Weg irrelevant; er lohnt sich ausschließlich für interne, admin-genutzte GraphQL-Endpunkte wie diesen Report.

Achtung: Ein GraphQL-Endpunkt mit Admin-ACL-Prüfung bleibt trotzdem über die öffentlich erreichbare /graphql-URL ansprechbar - es gibt keinen separaten, IP-beschränkten "Admin-GraphQL"-Endpunkt. Der Schutz besteht ausschließlich in der Token-Validierung und der isAllowed()-Prüfung selbst; wer diese Prüfung vergisst, exponiert interne Daten unter derselben URL wie den öffentlichen Produktkatalog.

Mit N+1-Lösung, Caching, Uploads und ACL ist Block 6 abgeschlossen - die Veranstaltungen-API ist performant, cachefähig, medienfähig und granular absicherbar. Block 7 schließt die Serie mit Test-Strategien, Debugging-Praxis und einem zusammenfassenden Spickzettel ab.