kees prince
kees prince

Reputation: 11

zlib deflated samlrequest returns a "not deflated propper" by azure AD

i am using c++ zlib to deflate a XML string that gives the output:

<samlp:AuthnRequest
  xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
  ID="idnumber"
  Version="2.0" IssueInstant="2026-09-30T15:12:00.1839884Z"
  xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
  <Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">tenantID</Issuer>
</samlp:AuthnRequest>

the xml is put into a stringstream as follow with rapidxml:

xml << "<samlp:AuthnRequest \n" <<
     "xmlns=\"urn:oasis:names:tc:SAML:2.0:metadata\" \n " <<
     "ID=\"idnumber\" \n " <<
     "Version=\"2.0\" IssueInstant=\"2022-09-30T16:00:00.1839884Z\"\n " <<
     "xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\">\n" <<
     "<Issuer xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\">" + tenantIDstring + "</Issuer>\n" <<     "</samlp:AuthnRequest>";

When i deflate and then b64 encode then url encode it, it returns thestring that should be sent over the url for the SAMLRequest of azure AD. So its working as it should and is deflating the xml.

But the response from Azure AD return that the request is not deflated propperly. i am using the deflate.h from zlib.

deflate_xml.h:

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <string>
#include <vector>
#include <iostream>
#include "rapidxml.hpp"
#include <zlib.h>

namespace helper
{
    static std::string deflate_file(const std::string &str, // gets filled with xml.str(); from the main.cpp
                        int compressionlevel = Z_BEST_COMPRESSION)
    {
        z_stream zs; // z_stream is zlib's control structure
        memset(&zs, 0, sizeof(zs));

        if (deflateInit(&zs, compressionlevel) != Z_OK)
            throw(std::runtime_error("deflateInit failed while compressing."));

        zs.next_in = (Bytef *)str.data();
        zs.avail_in = str.size(); // set the z_stream's input

        int ret;
        char outbuffer[32768];
        std::string outstring;

        // retrieve the compressed bytes blockwise
        do
        {
            zs.next_out = reinterpret_cast<Bytef *>(outbuffer);
            zs.avail_out = sizeof(outbuffer);

            ret = deflate(&zs, Z_FINISH);

            if (outstring.size() < zs.total_out)
            {
                // append the block to the output string
                outstring.append(outbuffer,
                                 zs.total_out - outstring.size());
            }
        } while (ret == Z_OK);

        deflateEnd(&zs);

        if (ret != Z_STREAM_END)
        { // an error occurred that was not EOF
            std::ostringstream oss;
            oss << "Exception during zlib compression: (" << ret << ") " << zs.msg;
            throw(std::runtime_error(oss.str()));
        }

        return outstring;
    }

Whats seems to be going amis here. Am i using the wrong deflation algorithm ? When i upload te xml string to a online deflate b64 enc. it gives me a string that is viable as a SAMLRequest. What diffrence is there in the zlib deflate and the online deflation ? (ref. https://developers.onelogin.com/saml/online-tools/code-decode/deflate-base64-encode)

Update:

Seems the online encoder in the ref, does something diffrent. I took the deflated example and put that in a diffrent base 64 encoder online. And now azure AD says its not base 64 encoded properly.. does anyone know what the difference is between the "normal deflation and standalone base64"and the one that certain website does ?

Upvotes: 1

Views: 983

Answers (1)

Mark Adler
Mark Adler

Reputation: 112502

From the reference online encoding linked in the question, Azure AD is expecting raw deflate data. To get that, replace the deflateInit() call with:

deflateInit2(&zs, compressionlevel, 8, -15, 8, 0)

Upvotes: 1

Related Questions