Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Service provider logs #112

Open
haunted2 opened this issue Jun 15, 2020 · 2 comments
Open

Service provider logs #112

haunted2 opened this issue Jun 15, 2020 · 2 comments

Comments

@haunted2
Copy link

haunted2 commented Jun 15, 2020

Hello.
The technical regulation for the implementation of SPID by service providers, require the conservation of the AuthnRequest and the related Response in logs for 24 months

https://docs.italia.it/italia/spid/spid-regole-tecniche/it/stabile/log.html#service-provider

Unfortunately, in this library i can't find methos to easily obtain these information without hacking the original code (AuthRequest and BaseResponse classes)

Any suggestions about the best way to implement this functionality?

Thanks.

@lorenzocattaneo
Copy link
Collaborator

Hello @haunted2, thank you for reporting this.
Unfortunately there is no method to directly get the data you need. You have 2 solutions at the moment:

  1. updating the code of the library
  2. manually doing all the operations that $sp->login(...) would normally do as a temporary fix. At the end of this post you can see an example of how that could look like, for reference.

I'll probably be able to send a proper fix and update in about a couple weeks. If you can't wait I suggest just hacking into the code and saving the data the moment it is generated. In case you wish to contribute we can discuss a more solid solution, just let me know.

//AUTHN REQUEST IS BUILT DURING THE LOGIN PROCESS
//THE XML IS GENERATED IN Idp.php METHOD authnRequest(...)
//ALL METHODS CALLED BY $sp->login(...) ARE PUBLIC, SO WE CAN 
//CALL THEM MANUALLY AND INTERCEPT THE XML CREATION
function customLogin(
    Sp $sp,
    $binding,
    $idpName,
    $assertId,
    $attrId,
    $level = 1,
    $redirectTo = null,
    $shouldRedirect = true
    ) {
    if ($sp->isAuthenticated()) {
        return false;
    }
    if (!array_key_exists($assertId, $sp->settings['sp_assertionconsumerservice'])) {
        throw new \Exception("Invalid Assertion Consumer Service ID");
    }
    if (isset($sp->settings['sp_attributeconsumingservice'])) {
        if (!isset($sp->settings['sp_attributeconsumingservice'][$attrId])) {
            throw new \Exception("Invalid Attribute Consuming Service ID");
        }
    } else {
        $attrId = null;
    }
    $idp = $sp->loadIdpFromFile($idpName);

    $idp->assertID = $assertId;
    $idp->attrID = $attrId;
    $idp->level = $level;

    $authn = new AuthnRequest($idp);
    $url = $binding == Settings::BINDING_REDIRECT ?
        $authn->redirectUrl($redirectTo) :
        $authn->httpPost($redirectTo);

    /*==================
    ACCESS THE AUTHNREQUEST XML HERE WITH 
    $authn->xml
    THEN CONTINUE WITH THE REQUEST
    ==================*/

    $_SESSION['RequestID'] = $authn->id;
    $_SESSION['idpName'] = $idp->idpFileName;
    $_SESSION['idpEntityId'] = $idp->metadata['idpEntityId'];
    $_SESSION['acsUrl'] = $idp->sp->settings['sp_assertionconsumerservice'][$ass];

    if (!$shouldRedirect || $binding == Settings::BINDING_POST) {
        return $url;
    }

    header('Pragma: no-cache');
    header('Cache-Control: no-cache, must-revalidate');
    header('Location: ' . $url);
    exit("");
}

//THE RESPONSE IS NORMALLY BUILT FROM EITHER $_POST OR $_GET DATA IN $sp->isAuthenticated()
//$_POST AND $_GET ARE NOT CLEARED SO YOU CAN REBUILD THE RESPONSE XML FROM THE DATA AFTER VERIFYING THE 
//RESPONSE IS CORRECT WITH $sp->isAuthenticated()
function getResponseXML(): ?string {
    if ((!isset($_POST) || !isset($_POST['SAMLResponse'])) &&
        (!isset($_GET) || !isset($_GET['SAMLResponse']))
    ) {
        return null;
    }
    $xmlString = isset($_GET['SAMLResponse']) ?
        gzinflate(base64_decode($_GET['SAMLResponse'])) :
        base64_decode($_POST['SAMLResponse']);
    
    $xml = new \DOMDocument();
    $xml->loadXML($xmlString);
    
    $ns_samlp = 'urn:oasis:names:tc:SAML:2.0:protocol';
    $root = $xml->getElementsByTagNameNS($ns_samlp, '*')->item(0)->localName;

    if ($root != 'Response') return null;
        
    if (isset($_SESSION['spidSession'])) {
        return null;
    }
    return $xml;
}

@haunted2
Copy link
Author

Thank you very much!
Looking at your example, i managed to log the data i need.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants