Back to top

Autore Topic: [RISOLTO] Pagine AMP - amp-consent e checkConsentHref endpoint  (Letto 3567 volte)

Offline danielecr

  • Abituale
  • ****
  • Post: 1357
    • Mostra profilo
Ciao a tutti,
scrivo in questa sezione perchè l'argomento non centra una mazza con joomla, ma può magari diventare utile per qualcuno.
Ho implementato in parallelo al sito in joomla delle pagine AMP: per bloccare alcuni elementi delle pagine previo consenso del visitatore (come cookies analitici) ho utilizzato il recente "amp-consent" ( https://www.ampproject.org/docs/reference/components/amp-consent ).
"amp-consent" necessita di un endpoint per funzionare a dovere, per verificare lo stato del consenso dato dal visitatore.
Tuttora, e quando ho implementato le pagine AMP, non avevo trovato esempi concreti a riguardo, o comunque non chiarissimi (almeno per me) e ho cercato di seguire le indicazioni date su ampproject.org - https://www.ampproject.org/docs/fundamentals/amp-cors-requests

In particolare, seguendo la documentazione, si dice:
Citazione
If `Origin` header is set:

1. If the origin was not `*.ampproject.org`, `*.amp.cloudflare.com` or the publisher's (aka your) origin, stop and return an error response.
2. Check the `__amp_source_origin` query parameter. If it's not the publisher's origin stop and return an error response.
3. If both checks pass, proceed to process the request.

Otherwise, if `Origin` header is NOT set:

1. Check if the request has `AMP-Same-Origin: true` header. If not, stop and return an error response.
    * This custom request header is sent by AMP runtime when making an XHR request on sameorigin (document served from non-cache URL).
2. Otherwise proceed to process the request.

It's very important that these all are done first before processing the request, this provides protection against CSRF attacks and avoids processing untrusted sources requests.

Si tratta quindi di effettuare una richiesta CORS di tipo POST a un endpoint, che ho scritto in php.

Premettendo che il dominio è indicato come mio-dominio.com, che ho un certificato https attivo e che ho i redirezionamenti da non-www a www e da http a https --> qui di seguito il codice dell'endpoint che ho scritto:

Codice: [Seleziona]
<?php
if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
   if (isset(
$_SERVER['HTTP_ORIGIN'])) {
      
$http_origin $_SERVER['HTTP_ORIGIN'];
      
$amp_origin $_REQUEST['__amp_source_origin'];
      if ((
$http_origin == "https://www-mio--dominio-com.cdn.ampproject.org" || $http_origin == "https://mio--dominio-com.cdn.ampproject.org" || $http_origin == "https://cdn.ampproject.org" || $http_origin == "https://www-mio--dominio-com.amp.cloudflare.com" || $http_origin == "https://mio--dominio-com.amp.cloudflare.com" || $http_origin == "https://www.mio-dominio.com" || $http_origin == "https://mio-dominio.com") && ($amp_origin == "https://www.mio-dominio.com" || $amp_origin == "https://mio-dominio.com")) {
         
header("access-control-allow-credentials:true");
         
header("access-control-allow-headers:Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token");
         
header("access-control-allow-methods:POST");
         
header("access-control-allow-origin:".$_SERVER['HTTP_ORIGIN']);
         
header("access-control-expose-headers:AMP-Access-Control-Allow-Source-Origin");
         
header("amp-access-control-allow-source-origin:".$_REQUEST['__amp_source_origin']);
         
header("Content-Type: application/json");
         
$output = new \stdClass();
             
$output->promptIfUnknown true;
             echo 
json_encode($output);
      }
      else {
         echo(
"something went wrong");
      }
   }
   else {
      
$ampsameoriginvalue "";
      foreach (
getallheaders() as $name => $value) {
         if (
strtoupper($name) == "AMP-SAME-ORIGIN") {
            
$ampsameoriginvalue $value;
         }
      }
      if (
$ampsameoriginvalue == "true") {
         
$amp_origin $_REQUEST['__amp_source_origin'];
         if (
$amp_origin == "https://www.mio-dominio.com" || $amp_origin == "https://mio-dominio.com") {
            
header("access-control-allow-credentials:true");
            
header("access-control-allow-headers:Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token");
            
header("access-control-allow-methods:POST");
            
header("access-control-allow-origin:https://www.mio-dominio.com");
            
header("access-control-expose-headers:AMP-Access-Control-Allow-Source-Origin");
            
header("amp-access-control-allow-source-origin:".$_REQUEST['__amp_source_origin']);
            
header("Content-Type: application/json");
            
$output = new \stdClass();
                
$output->promptIfUnknown true;
                echo 
json_encode($output);
         }
         else {
            echo(
"something went wrong");
         }
      }
      else {
         echo(
"something went wrong");
      }
   }
}
else {
   echo 
"post only";
}
?>


Quello che fa è:
1- verifica che la richiesta sia POST, altrimenti dai un messaggio di errore
2- verifica se l'header Origin è presente
3- se l'header Origin è presente: se il valore dell'header Origin è in whitelist e se amp origin è in whitelist, imposta gli header di risposta e procedi alla richiesta CORS, altrimenti dai un messaggio di errore
4- se l'header Origin non è presente verifica se negli header di richiesta esiste Amp-Same-Origin: true
5- se Amp-Same-Origin: true è presente imposta gli header e procedi alla richiesta CORS, altrimenti dai un messaggio di errore
6- se l'header Amp-Same-Origin: true non esiste dai un messaggio di errore

Ora, mi sembra che funzioni tutto correttamente, sia nella cache AMP, sia aprendo le pagine AMP direttamente su mio-dominio.com, ma visto che è la prima volta che mi approccio a CORS, magari mi è sfuggito qualcosa, magari a livello di sicurezza.

Anche perchè fino ad oggi, tutte le volte che ho aperto questo file l'ho modificato.... ::)

Magari se qualcuno ha voglia scorrendo il codice può capire se ho seguito correttamente il flusso delle istruzioni, o se ho fatto qualche cazzata...

EDIT: ops, mi sono accorto che https://www.ampproject.org/docs/fundamentals/amp-cors-requests è stato aggiornato e ora c'è un esempio in javascript.
« Ultima modifica: 22 Lug 2018, 09:53:13 da danielecr »

Offline Alex21

  • Appassionato
  • ***
  • Post: 645
    • Mostra profilo
Re:Pagine AMP - amp-consent e checkConsentHref endpoint
« Risposta #1 il: 19 Lug 2018, 22:53:25 »
EDIT: ops, mi sono accorto che https://www.ampproject.org/docs/fundamentals/amp-cors-requests è stato aggiornato e ora c'è un esempio in javascript.
Sì, certo è una convalida di richiesta ajax ( xhr ), fac-simile alla tua, lato server per un server che monta node.js.
Una cosa mi stavo chiedendo leggendo il tuo codice. Se la white list è bella lunga, mi sa che ti occorre un sistema più efficiente di una sequenza di
or ( || ) per testarla.
Ciao!

Offline danielecr

  • Abituale
  • ****
  • Post: 1357
    • Mostra profilo
Re:Pagine AMP - amp-consent e checkConsentHref endpoint
« Risposta #2 il: 21 Lug 2018, 09:37:34 »
Grazie del commento Alex, la whitelist non dovrebbe essere più lunga di quella scritta, ovvero comprende tutti gli indirizzi di cache e il proprio dominio (entrambi in versione www e non www).In effetti è un po' al limite..

Sarebbe più efficiente creare due array e fare il check su questi secondo te?

Codice: [Seleziona]
$whitelist_origin = array('https://www-my--domain-com.cdn.ampproject.org', 'https://my--domain-com.cdn.ampproject.org', 'https://cdn.ampproject.org', 'https://www-my--domain-com.amp.cloudflare.com', 'https://my--domain-com.amp.cloudflare.com', 'https://www.my-domain.com', 'https://my-domain.com');

$whitelist_amp_origin = array('https://www.my-domain.com', 'https://my-domain.com');
 
if((in_array($http_origin, $whitelist_origin)) && (in_array($amp_origin, $whitelist_amp_origin))) {
...
}
« Ultima modifica: 21 Lug 2018, 09:47:40 da danielecr »

Offline Alex21

  • Appassionato
  • ***
  • Post: 645
    • Mostra profilo
Re:Pagine AMP - amp-consent e checkConsentHref endpoint
« Risposta #3 il: 21 Lug 2018, 11:26:45 »
Sarebbe più efficiente creare due array e fare il check su questi secondo te?
Secondo me, sì.
Adesso so di rompere le scatole, ma in_array() è case sensitive, vuol dire che se qualche buontempone ti manda una stringa così, per esempio: 'https://Www.my-domain.comdiventa un falso positivo, dovrebbe passare e non lo fa. La cosa ( purtroppo ) costringe ad una certa manipolazione preventiva della stringa, previo filtraggio della medesima.
Ciao!

Offline danielecr

  • Abituale
  • ****
  • Post: 1357
    • Mostra profilo
Re:Pagine AMP - amp-consent e checkConsentHref endpoint
« Risposta #4 il: 22 Lug 2018, 09:52:54 »
Grazie,per maiuscole/minuscole sui domini non mi preoccuperei, perchè le richieste sono interne, e sono sempre tutte in minuscolo, quindi non c'è motivo di alterarla con lettere maiuscole (e se fosse alterata di proposito allora per me sarebbe giusto un errore 401). Visto anche l'esempio, per me è risolto, metto qui il codice definitivo, ho ancora cambiato gli errori da echo a 401, e inserito il check sui vettori.
Codice: [Seleziona]
<?php
if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
    
$whitelist_origin = array('https://www-my--domain-com.cdn.ampproject.org''https://my--domain-com.cdn.ampproject.org''https://cdn.ampproject.org''https://www-my--domain-com.amp.cloudflare.com''https://my--domain-com.amp.cloudflare.com''https://www.my-domain.com''https://my-domain.com');
    
$whitelist_amp_origin = array('https://www.my-domain.com''https://my-domain.com');
    if (isset(
$_SERVER['HTTP_ORIGIN'])) {
        
$http_origin $_SERVER['HTTP_ORIGIN'];
        
$amp_origin $_REQUEST['__amp_source_origin'];
        if((
in_array($http_origin$whitelist_origin)) && (in_array($amp_origin$whitelist_amp_origin))) {
            
header("access-control-allow-credentials:true");
            
header("access-control-allow-headers:Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token");
            
header("access-control-allow-methods:POST");
            
header("access-control-allow-origin:".$_SERVER['HTTP_ORIGIN']);
            
header("access-control-expose-headers:AMP-Access-Control-Allow-Source-Origin");
            
header("amp-access-control-allow-source-origin:".$_REQUEST['__amp_source_origin']);
            
header("Content-Type: application/json");
            
$output = new \stdClass();
            
$output->promptIfUnknown true;
            echo 
json_encode($output);
        }
        else {
            
header("HTTP/1.1 401 Unauthorized");
            echo 
"You are not authorized";
            exit;
        }
    }
    else {
        
$ampsameoriginvalue "";
        foreach (
getallheaders() as $name => $value) {
            if (
strtoupper($name) == "AMP-SAME-ORIGIN") {
                
$ampsameoriginvalue $value;
            }
        }
        if (
$ampsameoriginvalue == "true") {
            
$amp_origin $_REQUEST['__amp_source_origin'];
            if(
in_array($amp_origin$whitelist_amp_origin)) {
                
header("access-control-allow-credentials:true");
                
header("access-control-allow-headers:Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token");
                
header("access-control-allow-methods:POST");
                
header("access-control-allow-origin:https://www.my-domain.com");
                
header("access-control-expose-headers:AMP-Access-Control-Allow-Source-Origin");
                
header("amp-access-control-allow-source-origin:".$_REQUEST['__amp_source_origin']);
                
header("Content-Type: application/json");
                
$output = new \stdClass();
                
$output->promptIfUnknown true;
                echo 
json_encode($output);
            }
            else {
                
header("HTTP/1.1 401 Unauthorized");
                echo 
"You are not authorized";
                exit;
            }
        }
        else {
            
header("HTTP/1.1 401 Unauthorized");
            echo 
"You are not authorized";
            exit;
        }
    }
}
else {
    
header("HTTP/1.1 401 Unauthorized");
    echo 
"You are not authorized";
    exit;
}
?>

« Ultima modifica: 22 Lug 2018, 11:02:50 da danielecr »

 



Web Design Bolzano Kreatif