From: dtgames@... Date: 2017-11-01T16:07:12+00:00 Subject: [ruby-core:83637] [Ruby trunk Bug#14071] HTTP Header requiring dual authorization fails with 'header field value cannot include CR/LF' Issue #14071 has been updated by dgames (Dax Games). Thanks all for the responses. Unfortunately I do not have the capability to ''fix ' the server and a header similar to the header resulting from my 2nd and 3rd failed examples works in a nodejs sample app but not in Ruby. Where the header is defined as a hash: ``` header = { 'authorization' => ["Bearer #{pf_token}", "#{ck_token}"], 'oauth_clientid' => pf_credentials['client_id'], 'content-type' => 'application/json' } ``` # Working NodeJS Sample ``` let options = { method: 'GET', url: 'https://xxxxxxx/v1/PasswordVault/WebServices/PIMServices.svc/Safes', qs: { client_id: 'ClientId1', client_secret: 'ClientSecret1', grant_type: 'client_credentials', scope: 'api' }, headers: { 'Authorization': ['Bearer ' + pftoken, cktoken], 'oauth_clientid': 'clientid1', 'content-type': 'application/json' } }; console.log(options.headers); request(options, function (error, response, body) { if (error) { reject(error); } resolve(body); }); ``` So this leads me to believe the server is not the issue. This was my main concern, wondering if there is some issue with the way ruby is dealing with it? I will try the comma separated string. I think I already did that but will try again. ---------------------------------------- Bug #14071: HTTP Header requiring dual authorization fails with 'header field value cannot include CR/LF' https://bugs.ruby-lang.org/issues/14071#change-67665 * Author: dgames (Dax Games) * Status: Third Party's Issue * Priority: Normal * Assignee: * Target version: * ruby -v: ruby 2.4.2p198 (2017-09-14 revision 59899) [x86_64-linux] * Backport: 2.3: UNKNOWN, 2.4: UNKNOWN ---------------------------------------- Not sure if this is a bug or not but I know where it was introduced and when it worked. ruby 2.3.1p112 (Code Works) ruby 2.3.4p301 (Code Works) ruby 2.3.5p376 (Code Fails) ruby 2.4.1p111 (Code Works) ruby 2.4.2p198 (Code Fails) My code that works - (Depending on Ruby version - see above versions of ruby for pass fail status): # Start Working Code ```ruby url = my_url + "/PasswordVault/WebServices/PIMServices.svc/Accounts?Safe=" + safe url += "&Keywords=" + keywords if ! keywords.nil? uri = URI.parse(url) http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["authorization"] = "Bearer #{pf_token}\r\nAuthorization: #{ck_token}" request["oauth_clientid"] = pf_credentials['client_id'] request["content-type"] = 'application/json' # Send the request http.set_debug_output $stderr res = http.request(request) ``` I am no expert and the code above may be a hack but it works on sites where dual authentication is required, at least with some versions of Ruby. I came to this solution by inspecting the http request by setting '`http.set_debug_output $stderr`' and saw that header elements are separate by '\r\n' This curl command works: ``` curl -X GET 'https://xxxx/PasswordVault/WebServices/PIMServices.svc/Accounts?Safe=Safe1' -H 'authorization: Bearer xxxxxxxxxxxxxxxxxxx' -H 'authorization: YYYYYYYYYYY' -H 'content-type: application/json' -H 'oauth_clientid: clientid1' ``` The above code fails with 'header field value cannot include CR/LF' in: ruby 2.3.5p376 ruby 2.4.2p198 This was most recently was re-introduced by this commit: https://github.com/ruby/ruby/commit/427f5b57135fa165990f87c93658fafbe070289f I have tried the following on the newer failing version of Ruby but these also fail with `#<Net::HTTPUnauthorized:0x0000000003183780> => "1012116 - Invalid token."` # Start Failing Code ```ruby url = my_url + "/PasswordVault/WebServices/PIMServices.svc/Accounts?Safe=" + safe url += "&Keywords=" + keywords if ! keywords.nil? uri = URI.parse(url) http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request["authorization"] = ["Bearer #{pf_token}", ck_token] request["oauth_clientid"] = pf_credentials['client_id'] request["content-type"] = 'application/json' # Send the request http.set_debug_output $stderr res = http.request(request) ``` and this: ```ruby url = my_url + "/PasswordVault/WebServices/PIMServices.svc/Accounts?Safe=" + safe url += "&Keywords=" + keywords if ! keywords.nil? uri = URI.parse(url) http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Get.new(url) request.add_field("authorization", "Bearer #{pf_token}") request.add_field("authorization", ck_token) request.add_field("oauth_clientid", pf_credentials['client_id']) request.add_field("content-type", 'application/json') # Send the request http.set_debug_output $stderr res = http.request(request) ``` Another variation also fails in all versions with `"undefined method `strip' for #<Array:0x00000000034ad910>"` ```ruby url = my_url + "/PasswordVault/WebServices/PIMServices.svc/Accounts?Safe=" + safe url += "&Keywords=" + keywords if ! keywords.nil? uri = URI.parse(url) http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true header = { 'authorization' => ["Bearer #{pf_token}", "#{ck_token}"], 'oauth_clientid' => pf_credentials['client_id'], 'content-type' => 'application/json' } # Send the request http.set_debug_output $stderr res = http.request_get(uri.path, header) ``` -- https://bugs.ruby-lang.org/ Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe> <http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>