From 59f4da2350e1630fd8951f72b9c439f455acd9b0 Mon Sep 17 00:00:00 2001 From: Matt Robinson Date: Tue, 20 Mar 2018 15:10:15 -0700 Subject: [PATCH] HTML encode SOAP login info Encode otherwise response comes back with error like UNKNOWN_EXCEPTION: The reference to entity "v4Hq" must end with the ';' delimiter. --- lib/forcex/auth/session_id.ex | 6 +++++- mix.exs | 3 ++- mix.lock | 1 + test/forcex/client_test.exs | 38 +++++++++++++++++++++++++---------- 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/lib/forcex/auth/session_id.ex b/lib/forcex/auth/session_id.ex index d0dda57..6d03ea8 100644 --- a/lib/forcex/auth/session_id.ex +++ b/lib/forcex/auth/session_id.ex @@ -12,6 +12,10 @@ defmodule Forcex.Auth.SessionId do schema_instance = "http://www.w3.org/2001/XMLSchema-instance" env = "http://schemas.xmlsoap.org/soap/envelope/" + # Encode otherwise response comes back with error like + # UNKNOWN_EXCEPTION: The reference to entity "v4Hq" must end with the ';' delimiter. + conf = for {key, val} <- conf, into: %{}, do: {key, HtmlEntities.encode(val)} + body = """ @@ -29,7 +33,7 @@ defmodule Forcex.Auth.SessionId do {"SOAPAction", "login"} ] - url = "https://login.salesforce.com/services/Soap/u/#{starting_struct.api_version}" + url = starting_struct.endpoint <> "/services/Soap/u/#{starting_struct.api_version}" Logger.debug("api=#{@api}") @api.raw_request(:post, url, body, headers, []) diff --git a/mix.exs b/mix.exs index fc5ec78..ae0b884 100644 --- a/mix.exs +++ b/mix.exs @@ -71,7 +71,8 @@ defmodule Forcex.Mixfile do {:earmark, "~> 1.1", only: :dev, override: true}, {:dialyxir, "~> 0.4", only: :dev}, {:mox, "~> 0.3", only: :test}, - {:mix_test_watch, "~> 0.5", only: [:dev, :test], runtime: false} + {:mix_test_watch, "~> 0.5", only: [:dev, :test], runtime: false}, + {:html_entities, "~> 0.4"} ] end diff --git a/mix.lock b/mix.lock index 5d60ef8..db360eb 100644 --- a/mix.lock +++ b/mix.lock @@ -10,6 +10,7 @@ "fs": {:hex, :fs, "0.9.2", "ed17036c26c3f70ac49781ed9220a50c36775c6ca2cf8182d123b6566e49ec59", [:rebar], [], "hexpm"}, "gettext": {:hex, :gettext, "0.13.1", "5e0daf4e7636d771c4c71ad5f3f53ba09a9ae5c250e1ab9c42ba9edccc476263", [], [], "hexpm"}, "hackney": {:hex, :hackney, "1.10.1", "c38d0ca52ea80254936a32c45bb7eb414e7a96a521b4ce76d00a69753b157f21", [], [{:certifi, "2.0.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, + "html_entities": {:hex, :html_entities, "0.4.0", "f2fee876858cf6aaa9db608820a3209e45a087c5177332799592142b50e89a6b", [:mix], [], "hexpm"}, "httpoison": {:hex, :httpoison, "0.13.0", "bfaf44d9f133a6599886720f3937a7699466d23bb0cd7a88b6ba011f53c6f562", [], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, "idna": {:hex, :idna, "5.1.0", "d72b4effeb324ad5da3cab1767cb16b17939004e789d8c0ad5b70f3cea20c89a", [], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, "jsx": {:hex, :jsx, "2.8.3", "a05252d381885240744d955fbe3cf810504eb2567164824e19303ea59eef62cf", [], [], "hexpm"}, diff --git a/test/forcex/client_test.exs b/test/forcex/client_test.exs index 09b098b..e23f29f 100644 --- a/test/forcex/client_test.exs +++ b/test/forcex/client_test.exs @@ -5,33 +5,49 @@ defmodule Forcex.ClientTest do setup :verify_on_exit! describe "session_id based login" do - test "sets the auth header and endpoint when successful" do - session_id = "forcex_session_id" - server_url = "https://forcex.my.salesforce.com/services/Soap/u/41.0/00Dd0000000cQ8L" - org_id = "org_id" - - response = """ - #{server_url}falsefalse#{server_url}#{session_id}005d0000001Jb9tAACfalsefalse$5242880USDen_USfalsetrue#{org_id}falseMY-ORG00ed0000000Ods2AAC00Ed0000000II8UEAW7200forcex@example.comJohn Doe005d0000001Jb9tAACen_USen_USforcex@example.comAmerica/New_YorkStandardTheme3 + @session_id "forcex_session_id" + @server_url "https://forcex.my.salesforce.com/services/Soap/u/41.0/00Dd0000000cQ8L" + @org_id "org_id" + @response """ + #{@server_url}falsefalse#{@server_url}#{@session_id}005d0000001Jb9tAACfalsefalse$5242880USDen_USfalsetrue#{@org_id}falseMY-ORG00ed0000000Ods2AAC00Ed0000000II8UEAW7200forcex@example.comJohn Doe005d0000001Jb9tAACen_USen_USforcex@example.comAmerica/New_YorkStandardTheme3 """ - Forcex.Api.MockHttp - |> expect(:raw_request, fn :post, _, _, _, _ -> response end) - + test "sets the auth header and endpoint when successful" do config = %{ password: "password", security_token: "security_token", username: "forcex@example.com" } + Forcex.Api.MockHttp + |> expect(:raw_request, fn :post, _, _, _, _ -> @response end) + client = Forcex.Client.login(config) assert client.authorization_header == [{ "Authorization", - "Bearer #{session_id}" + "Bearer #{@session_id}" }] assert client.endpoint == "https://forcex.my.salesforce.com/" end + + test "login info is HTML encoded" do + config = %{ + password: "amper&and", + security_token: "flash!", + username: "<>@example.com" + } + + encoded_config = for {key, val} <- config, into: %{}, do: {key, HtmlEntities.encode(val)} + + expected_body = "\n\n\n\n <<probablynotvalid>>@example.com\n amper&andflash!\n\n\n\n" + + Forcex.Api.MockHttp + |> expect(:raw_request, fn :post, _, ^expected_body, _, _ -> @response end) + + client = Forcex.Client.login(config) + end end describe "oauth based login" do