blob: c2b38850f18d49f52e0712bc7dd2633d416070d0 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/enterprise/profile_management/saml_response_parser.h"
#include <string>
#include <vector>
#include "base/base64.h"
#include "base/containers/flat_map.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace profile_management {
using testing::_;
namespace {
const char kValidSAMLResponse[] = R"(
<samlp:Response ID="id" Version="2.0" Destination="https://dest.test">
<Issuer xmlns="urn:oasis:names:tc:SAML:2.0">https://issuer.com/</Issuer>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp:Status>
<Assertion ID="session" Version="2.0" xmlns="urn:oasis:names:tc:SAML:2.0">
<Issuer>https://issuer.com/</Issuer>
<Subject>
<NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">
user@domain.com
</NameID>
</Subject>
<AttributeStatement>
<Attribute Name="attribute">
<AttributeValue>attributevalue</AttributeValue>
</Attribute>
<Attribute Name="anotherattribute">
<AttributeValue>anotherattributevalue</AttributeValue>
</Attribute>
<Attribute Name="uselessattribute">
<AttributeValue>uselessattributevalue</AttributeValue>
</Attribute>
</AttributeStatement>
</Assertion>
</samlp:Response>)";
const char kHTMLTemplate[] = R"(
<html>
<body>
<form method="POST" name="hiddenform">
<input type="hidden" name="SAMLResponse" value="%s"/>
</form>
</body>
</html>)";
} // namespace
class SAMLResponseParserTest : public testing::Test {
public:
SAMLResponseParserTest() = default;
~SAMLResponseParserTest() override = default;
private:
base::test::SingleThreadTaskEnvironment task_environment_;
data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
};
TEST_F(SAMLResponseParserTest, RetrievesNoAttributesWithEmptyResponse) {
std::string response = "<html></html>";
base::flat_map<std::string, std::string> attributes;
base::RunLoop loop;
SAMLResponseParser body_reader(
std::vector<std::string>{"attribute", "notattribute", "anotherattribute"},
response,
base::BindLambdaForTesting(
[&attributes,
&loop](const base::flat_map<std::string, std::string>& result) {
attributes = std::move(result);
loop.Quit();
}));
loop.Run();
EXPECT_TRUE(attributes.empty());
}
TEST_F(SAMLResponseParserTest, RetrievesNoAttributesWithEmptySAMLResponse) {
std::string response = base::StringPrintf(kHTMLTemplate, "");
base::flat_map<std::string, std::string> attributes;
base::RunLoop loop;
SAMLResponseParser body_reader(
std::vector<std::string>{"attribute", "notattribute", "anotherattribute"},
response,
base::BindLambdaForTesting(
[&attributes,
&loop](const base::flat_map<std::string, std::string>& result) {
attributes = std::move(result);
loop.Quit();
}));
loop.Run();
EXPECT_TRUE(attributes.empty());
}
TEST_F(SAMLResponseParserTest, RetrievesSpecifiedAttributesWithValidResponse) {
std::string encoded_saml_response = base::Base64Encode(kValidSAMLResponse);
std::string response =
base::StringPrintf(kHTMLTemplate, encoded_saml_response.c_str());
base::flat_map<std::string, std::string> attributes;
base::RunLoop loop;
SAMLResponseParser body_reader(
std::vector<std::string>{"attribute", "notattribute", "anotherattribute"},
response,
base::BindLambdaForTesting(
[&attributes,
&loop](const base::flat_map<std::string, std::string>& result) {
attributes = std::move(result);
loop.Quit();
}));
loop.Run();
EXPECT_EQ(attributes["attribute"], "attributevalue");
EXPECT_EQ(attributes["anotherattribute"], "anotherattributevalue");
EXPECT_EQ(attributes.find("notattribute"), attributes.end());
EXPECT_EQ(attributes.find("uselessattribute"), attributes.end());
EXPECT_EQ(attributes[SAMLResponseParser::kDestinationUrl],
"https://dest.test");
}
} // namespace profile_management