Ergebnis 1 bis 22 von 22

Thema: Externe geschützte REST-Schnittstelle

  1. #1
    Contao-Nutzer Avatar von dako314
    Registriert seit
    04.05.2013.
    Ort
    Mannheim
    Beiträge
    120

    Standard Externe geschützte REST-Schnittstelle

    Hallo zusammen,

    ich habe vor innerhalb einer Contao-Anwendung eine geschützte Schnittstelle nach außen anzubieten, damit der Kunde per API-Request Member löschen kann, die nicht mehr benötigt werden.

    Dazu habe ich nun im vorhandenen Modul mir überlegt einen Eintrag in der routes.yml vorzunehmen und einen entsprechenden Controller anzulegen, der die Löschung vornehmen kann.

    PHP-Code:
    dakitec_xxx.member_controller.delete_callback:
      
    path: /api/member/{email}/delete
      defaults
    :
        
    _scopefrontend
        _controller
    Dakitec\xxx\Controller\MemberController::deleteCallback 
    Wie kann ich solch eine Route absichern? Denn ansonsten könnte diese ja einfach jeder aufrufen? Gibt es da von Haus aus Möglichkeiten oder programmiere ich am besten selbst etwas? Ich hatte irgendwie an einen API-Key oder einen Login mit dem Backend-User gedacht. Was hat es in dem Zusammenhang mit dem Attribut "_scope" auf sich? Das ist bei mir noch auf "frontend" gesetzt, habe gesehen es gibt auch "backend".

    Ich danke euch für eure Antworten.

    Viele Grüße
    Daniel Koch

  2. #2
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    34.063
    Partner-ID
    10107

    Standard

    Dafür machst du am besten einen eigenen Eintrag in der Symfony Firewall. Das einfachste Beispiel dazu wäre eine HTTP Basic Authentication, da das keinen zusätzlichen Code erfordert (für einen User Provider) - wenn es ok ist, dass Benutzername & Passwort direkt in PHP hardgecodet ist. In der Contao Managed Edition kannst du die Firewall über ein Contao Manager Plugin anpassen.

    Beispiel inklusive Route Definition, Controller & Contao Manager Plugin:

    PHP-Code:
    # config/routes.yml
    app.controller:
        
    resource: ../src/Controller
        type
    annotation 
    PHP-Code:
    // src/Controller/Api/ExampleApiController.php
    namespace App\Controller\Api;

    use 
    Symfony\Component\HttpFoundation\JsonResponse;
    use 
    Symfony\Component\HttpFoundation\Request;
    use 
    Symfony\Component\HttpFoundation\Response;
    use 
    Symfony\Component\Routing\Annotation\Route;

    /**
     * @Route("/api/example",
     *   name=ExampleApiController::class,
     *   methods="GET",
     *   condition="request.headers.get('Content-Type') matches '|application/json|i'"
     * )
     */
    class ExampleApiController
    {
        public function 
    __invoke(Request $request): Response
        
    {
            return new 
    JsonResponse('Hello World!');
        }

    PHP-Code:
    // src/ContaoManager/Plugin.php
    namespace App\ContaoManager;

    use 
    Contao\ManagerPlugin\Config\ContainerBuilder;
    use 
    Contao\ManagerPlugin\Config\ExtensionPluginInterface;
    use 
    Symfony\Component\Security\Core\User\User;

    /**
     * Plugin for the Contao Manager.
     */
    class Plugin implements ExtensionPluginInterface
    {
        public function 
    getExtensionConfig($extensionName, array $extensionConfigsContainerBuilder $container)
        {
            if (
    'security' !== $extensionName) {
                return 
    $extensionConfigs;
            }

            foreach (
    $extensionConfigs as &$extensionConfig) {
                if (isset(
    $extensionConfig['firewalls'])) {
                    
    // Set the password encoder for our user
                    
    $extensionConfig['encoders'][User::class] = 'auto';

                    
    // Define a new in-memory user provider
                    
    $extensionConfig['providers']['app.api_user_provider'] = [
                        
    'memory' => [
                            
    'users' => [
                                
    'api' => ['password' => '…'],
                            ],
                        ],
                    ];

                    
    // Insert a new firewall entry before Contao's for routes starting with /api/* and use our user provider
                    
    $offset = (int) array_search('contao_frontend'array_keys($extensionConfig['firewalls']), true);

                    
    $extensionConfig['firewalls'] = array_merge(
                        \
    array_slice($extensionConfig['firewalls'], 0$offsettrue), [
                            
    'app_api' => [
                                
    'pattern' => '/api/*',
                                
    'http_basic' => ['realm' => 'API'],
                                
    'provider' => 'app.api_user_provider',
                                
    'stateless' => true,
                            ],
                        ],
                        \
    array_slice($extensionConfig['firewalls'], $offsetnulltrue)
                    );

                    break;
                }
            }

            return 
    $extensionConfigs;
        }

    Dieses Contao Manager Plugin fügt vor der Contao Firewall einen weiteren Eintrag für alle Routes ein, die mit /api/ beginnen. Für diese Routes muss man sich dann über HTTP Basic Authentication mit Benutzername und Passwort authentifizieren.

    Nach anlegen der Dateien (im speziellen des Contao Manager Plugins) composer install ausführen.


    Benutzername und Passwort ist in dieser Zeile festgelegt, wobei das Passwort verschlüsselt sein muss:
    PHP-Code:
    'api' => ['password' => '…'], 
    Das verschlüsselte Passwort kannst du dir auf der Konsole folgendermaßen erzeugen lassen: vendor/bin/contao-console security:encode-password

    Symfony fragt dich danach, für welche User Klasse du ein Passwort erzeugen möchtest. Hier wählst du in diesem Fall Symfony\Component\Security\Core\User\User (nicht Contao\User), da wir diese Klasse in unserem Firewall Eintrag definiert haben.

    PHP-Code:
    vendor/bin/contao-console security:encode-password

    Symfony Password Encoder Utility
    ================================


     For 
    which user class would you like to encode a password? [Contao\User]:
      [
    0Contao\User
      
    [1Symfony\Component\Security\Core\User\User
     
    1
    1

     Type in your password to be encoded
    :
     >

     ------------------ ---------------------------------------------------------------------------------------------------
      
    Key                Value                                                                                             
     
    ------------------ ---------------------------------------------------------------------------------------------------
      
    Encoder used       Symfony\Component\Security\Core\Encoder\MigratingPasswordEncoder
      Encoded password   $argon2id$v
    =19$m=65536,t=4,p=1$ckZUelBJSXhEdHNxTTNlZw$6xy6DoIAR624uN7RWWlGh3JvJUU7GGEPjGTUh0hSj4Q
     
    ------------------ ---------------------------------------------------------------------------------------------------

     ! [
    NOTESelf-salting encoder usedthe encoder generated its own built-in salt.                                       

                                                                                                                            
     [
    OKPassword encoding succeeded 
    Das Encoded password kopierst du dir dann und fügst es im Contao Manager Plugin an der entsprechenden Stelle ein.
    Geändert von Spooky (06.02.2021 um 13:36 Uhr)

  3. #3
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    34.063
    Partner-ID
    10107

    Standard

    Zitat Zitat von dako314 Beitrag anzeigen
    Was hat es in dem Zusammenhang mit dem Attribut "_scope" auf sich? Das ist bei mir noch auf "frontend" gesetzt, habe gesehen es gibt auch "backend".
    Siehe dazu:


  4. #4
    Contao-Nutzer Avatar von dako314
    Registriert seit
    04.05.2013.
    Ort
    Mannheim
    Beiträge
    120

    Fehler

    Das hört sich vielversprechend an. Danke für die ausführliche Antwort.

    PS: Du hast bisher hier 99% meiner Contao-Probleme gelöst! Schade, dass deine Amazon-Wunschliste leer ist

    Viele Grüße,
    Daniel

  5. #5
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    34.063
    Partner-ID
    10107

    Standard

    Zitat Zitat von dako314 Beitrag anzeigen
    PS: Du hast bisher hier 99% meiner Contao-Probleme gelöst! Schade, dass deine Amazon-Wunschliste leer ist
    Man kann mich stattdessen auf GitHub sponsorn https://github.com/sponsors/fritzmg

    Siehe dazu auch https://youtu.be/ggGEK9bqjfY?t=716

  6. #6
    Contao-Nutzer Avatar von dako314
    Registriert seit
    04.05.2013.
    Ort
    Mannheim
    Beiträge
    120

    Standard

    Das mit der Firewall hat nun super geklappt.

    PS: Das Sponsoring übrigens auch - cool, dass es sowas gibt

  7. #7
    Contao-Nutzer
    Registriert seit
    30.07.2015.
    Beiträge
    140

    Standard

    ich habe das Beispiel mal ausprobiert. Unter der 4.13 bekommt man nach dem Login:

    HTML-Code:
    Call to a member function authenticate() on null
    EDIT: Der Controller musste bei mir entsprechend angepasst werden (Condition und Scope), dann läuft's
    Geändert von paddibr (02.06.2022 um 09:25 Uhr)

  8. #8
    Contao-Nutzer
    Registriert seit
    02.02.2024.
    Beiträge
    6

    Standard Contao 5.2.8

    Ich stehe gerade vor dem gleichen Problem und möchte meine API Schnittstelle mit einer eigenen Firewall schützen.
    Jetzt sieht es aber so aus, als ob das Contao-Manager-Plugin für diese Version nicht funktioniert.

    Darum hab ich jetzt versucht es in der /config/security.yaml selbst so zu konfigurieren:
    Code:
    security:
        firewalls:
            api:
                pattern: ^/api
                user_checker: App\Security\UserChecker
                access_token:
                    token_handler: App\Security\AccessTokenHandler
        access_control:
            - { path: ^/api, roles: ROLE_USER }
    Das scheint aber gar keine Auswirkungen zu haben.
    Hat jemand eine Idee oder einen Hinweis für mich?

  9. #9
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    34.063
    Partner-ID
    10107

    Standard

    Ich bin mir nicht sicher ob eine security.yaml in der Contao Manged Edition automatisch geladen wird. Selbst wenn würdest du dir damit die Contao Firewalls komplett überschreiben, da die Firewall Config von Symfony nicht gemerged wird, soweit ich weiß - daher der Weg über das Manager Plugin.
    » sponsor me via GitHub or PayPal or Revolut

  10. #10
    Contao-Nutzer
    Registriert seit
    02.02.2024.
    Beiträge
    6

    Standard

    OK, das heißt, ab Contao 5 wird es, dadurch dass das Manager Plugin nicht mehr funktioniert, etwas kompliziert eine Firewall zu erstellen?
    Zumindest muss man dann wohl tiefer in die Eingeweide von Contao um das umzusetzen. Hatte eigentlich gedacht mit der neueren Version wird mehr einfach

  11. #11
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    34.063
    Partner-ID
    10107

    Standard

    Mit Contao an sich hat das nichts zu tun, sondern mit Symfony - egal in welcher Contao Version (zumindest ab Contao 4.5).

    Die Vorgehensweise an sich funktioniert sicher auch in Contao 5 - was aber angepasst werden muss kann ich dir nicht aus dem FF sagen - man muss sich, wie du schon sagst, mit den "Eingeweiden" beschäftigen . Aber mit den Eingeweiden von Symfony.
    » sponsor me via GitHub or PayPal or Revolut

  12. #12
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    34.063
    Partner-ID
    10107

    Standard

    Zitat Zitat von slr82 Beitrag anzeigen
    Hatte eigentlich gedacht mit der neueren Version wird mehr einfach
    Das ist auch der Fall. In Symfony 6 hat sich die Security Component sehr stark geändert und vieles wurde vereinfacht.
    » sponsor me via GitHub or PayPal or Revolut

  13. #13
    Contao-Nutzer
    Registriert seit
    02.02.2024.
    Beiträge
    6

    Standard

    So, ich hab mich jetzt mal etwas damit auseinander gesetzt.

    Generell denke ich, sollte das eine machbare einfache Lösung sein, ich bin mir allerdings nicht sicher, ob ich den User nachher so richtig einlogge.

    Ich habe mir eine Klasse erstellt die Symfony\Component\EventDispatcher\EventSubscriberI nterface implementiert.
    Dort führe ich dann meinen Code beim KernelEvents::CONTROLLER Event aus.

    Hier kann ich dann auch prüfen, ob es sich um einen API Request handelt.
    Wie, weiß ich noch nicht genau, evtl. mit der Request URL oder ich lass meine API Klassen ein bestimmtes Interface implementieren auf das ich dort dann prüfen kann.

    Wenn dort der richtige Token im Request gesetzt ist, würde ich jetzt gerne auch an der Stelle den entsprechenden FrontendUser / Member einloggen.

    Mittels dependency injection hole ich mir dazu im Konstruktor folgende beiden Klasseninstanzen:
    private Security $security,
    private ContaoFramework $framework


    Und führe dann folgenden Code für den Login aus:
    PHP-Code:
    $this->framework->initialize();

    $member FrontendUser::getInstance();
    $member->findBy('username''xyz');

    $this->security->login($member'security.authenticator.remember_me.contao_frontend''contao_frontend'); 
    Das ist jetzt natürlich noch ein statischer User und wird später anhand von dem übergebenen Token gemacht.

    Im Controller der danach ausgeführt wird, ist der User dann auch eingeloggt und ich kann damit normal weiter arbeiten.

    Meine Frage ist jetzt, macht das so sinn, oder ist das total hacky und sollte besser anders umgesetzt werden?

  14. #14
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    34.063
    Partner-ID
    10107

    Standard

    Du solltest das auf jeden Fall über die Firewall machen. Nachdem du hier von Contao Frontend Mitgliedern sprichst ist es wohl am besten, dass dein Controller den Contao frontend _scope nutzt und du die Firewall um einen Authenticator erweiterst.
    » sponsor me via GitHub or PayPal or Revolut

  15. #15
    Contao-Nutzer
    Registriert seit
    02.02.2024.
    Beiträge
    6

    Standard

    Ich habe aber keine Möglichkeit gefunden die Firewall zu erweitern. In Symfony muss ich das ja eigentlich mit config/packages/security.yaml machen.
    Aber die Möglichkeit habe ich ja, so wie ich das verstanden habe mit Contao 5+ nicht so einfach.

    Deswegen der weg über die Event Subscription, was laut Symfony Dokumentation sogar mit Tokens zum Seitenschutz als Beispiel gezeigt wird (token-validation-example)

    Und dem Login habe ich auch so von der Symfony Doku (login-programmatically).

    Problem, dass ich jetzt eben auch hatte, ich kann mir in der Firewall keinen eigenen Authenticator registrieren, weil ich das in den yaml-Configurationsdateien nicht setzen kann.

    Selbst wenn ich dort in der config.yaml meinen eigenen Import der security.yaml einbinde:
    HTML-Code:
    imports:
        - { resource: security.yaml }
    Das führt nur zu einer Fehlerausgabe, die mir sagt, ich kann die firewall nur an einer Stelle konfigurieren.

  16. #16
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    34.063
    Partner-ID
    10107

    Standard

    Zitat Zitat von slr82 Beitrag anzeigen
    Ich habe aber keine Möglichkeit gefunden die Firewall zu erweitern. In Symfony muss ich das ja eigentlich mit config/packages/security.yaml machen.
    Aber die Möglichkeit habe ich ja, so wie ich das verstanden habe mit Contao 5+ nicht so einfach.
    Unabhängig von der Contao Version machst du das über ein Contao Manager Plugin (siehe meine vorigen Posts). Mit Contao 5 hat das nichts zu tun.


    Zitat Zitat von slr82 Beitrag anzeigen
    Das führt nur zu einer Fehlerausgabe, die mir sagt, ich kann die firewall nur an einer Stelle konfigurieren.
    Genau - wie gesagt musst du in der Contao Managed Edition dafür ein Contao Manager Plugin nutzen, um die Firewall bspw. mit zusätzlichen Authenticators zu versehen. Sowohl in Contao 4 als auch in Contao 5.
    Geändert von Spooky (07.02.2024 um 12:22 Uhr)
    » sponsor me via GitHub or PayPal or Revolut

  17. #17
    Contao-Nutzer
    Registriert seit
    02.02.2024.
    Beiträge
    6

    Standard

    Ok, sorry, dann hatte ich das vorhin falsch verstanden. Ich hatte ein Plugin gefunden das 'Contao Manager Plugin' heißt, aber nicht mit Contao 5+ geht.
    Das es Plugins vom Typ 'Manager Plugin' gibt, war mit so irgendwie noch nicht bewusst.
    Dann erst mal vielen Dank soweit. Ich werd mir das morgen mal genauer anschauen.

  18. #18
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    34.063
    Partner-ID
    10107

    Standard

    Zitat Zitat von slr82 Beitrag anzeigen
    Ich hatte ein Plugin gefunden das 'Contao Manager Plugin' heißt, aber nicht mit Contao 5+ geht.
    Das es Plugins vom Typ 'Manager Plugin' gibt, war mit so irgendwie noch nicht bewusst.
    Ich weiß jetzt leider nicht genau was du damit meinst. Mit "Contao Manager Plugin" bzw. "Manager Plugin" ist das selbe gemeint: https://docs.contao.org/dev/framework/manager-plugin/
    » sponsor me via GitHub or PayPal or Revolut

  19. #19
    Contao-Fan
    Registriert seit
    24.02.2021.
    Beiträge
    446

    Standard

    Zitat Zitat von Spooky Beitrag anzeigen
    Ich weiß jetzt leider nicht genau was du damit meinst. Mit "Contao Manager Plugin" bzw. "Manager Plugin" ist das selbe gemeint: https://docs.contao.org/dev/framework/manager-plugin/
    Wahrscheinlich Plugins, welche registriert werden:
    https://docs.contao.org/dev/framework/manager-plugin/

  20. #20
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    34.063
    Partner-ID
    10107

    Standard

    Auch da gibt es keinen Unterschied im Inhalt der Plugins.
    » sponsor me via GitHub or PayPal or Revolut

  21. #21
    Contao-Nutzer
    Registriert seit
    02.02.2024.
    Beiträge
    6

    Lächelndes Gesicht

    Ich hatte irgendwie eine Erweiterung/Paket für Contao gefunden, dass so hieß, weiß jetzt aber nicht mehr was ich da für nen Müll gefunden hatten. Das war aber nicht kompatibel mit Contao 5. Irgendwie war mir nicht bewusst, oder ich hab wohl nicht genau genug gelesen, dass das eine spezielle Art von Plugin ist. Aber gut, ich habs jetzt dank deiner Hilfe geschafft.

    Ich registriere mir mit dem Manager Plugin meine eigene Firewall, das klappt einwandfrei:
    Code:
    'api' => [
       'stateless' => true,
       'pattern' => '^/api(/|$)',
       'provider' => 'contao.security.frontend_user_provider',
       'custom_authenticator' => ApiTokenAuthenticator::class,
    ]
    Dabei kann ich sogar den Standard User Provider von Contao nutzen, da ich ja eh mit der Member Klasse arbeiten will.
    Ich musste mir nur einen eigenen Authenticator schreiben der AbstractAuthenticator erweitert, aus dem Request den Token ließt und entsprechend den passenden UserBadge zurück liefert.
    Also eigentlich doch viel einfacher wie gedacht

    Nochmal vielen Dank für die Hilfe und die Ausdauer mit meiner Blödheit

  22. #22
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    34.063
    Partner-ID
    10107

    Standard

    Genau so macht man das, ja . Und wie gesagt ist das in Symfony 6+ (ab Contao 5) noch einfacher als vorher.
    » sponsor me via GitHub or PayPal or Revolut

Aktive Benutzer

Aktive Benutzer

Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)

Lesezeichen

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •