CORS trouble between Sinatra and AngularJS - rest

I'm in troubles with a very basic web app. Here are my files:
public/index.html
<!DOCTYPE html>
<html lang="en" data-ng-app>
<body>
<div data-ng-controller="PlayersCtrl">
<div data-ng-repeat="player in players">
{{player.id}}
</div>
</div>
<script src="/angular.min.js"></script>
<script src="/players.js"></script>
</body>
</html>
public/players.js
function PlayersCtrl($scope, $http) {
$scope.players = [];
$http({
method: 'GET',
url: 'http://localhost:9292/hi'
}).success(function(data) {
$scope.players = data;
});
}
client.rb
require 'sinatra'
get '/' do
headers 'Access-Control-Allow-Origin' => '*'
headers 'Access-Control-Allow-Headers' => 'Authorization,Accepts,Content-Type,X-CSRF-Token,X-Requested-With'
headers 'Access-Control-Allow-Methods' => 'GET,POST,PUT,DELETE,OPTIONS'
send_file File.join(settings.public_folder, 'index.html')
end
api.rb
require 'sinatra'
require 'json'
get '/hi' do
headers 'Access-Control-Allow-Origin' => '*'
headers 'Access-Control-Allow-Headers' => 'Authorization,Accepts,Content-Type,X-CSRF-Token,X-Requested-With'
headers 'Access-Control-Allow-Methods' => 'GET,POST,PUT,DELETE,OPTIONS'
[id: 1, name: "Bob"].to_json
end
To me, this seems good. Then, I start the servers:
Starting api.rb
$ ruby api.rb -p 9292
[2013-03-07 23:57:43] INFO WEBrick 1.3.1
[2013-03-07 23:57:43] INFO ruby 2.0.0 (2013-02-24) [x86_64-darwin12.2.0]
== Sinatra/1.3.5 has taken the stage on 9292 for development with backup from WEBrick
[2013-03-07 23:57:43] INFO WEBrick::HTTPServer#start: pid=62634 port=9292
Starting client.rb
$ ruby client.rb
[2013-03-07 23:57:40] INFO WEBrick 1.3.1
[2013-03-07 23:57:40] INFO ruby 2.0.0 (2013-02-24) [x86_64-darwin12.2.0]
== Sinatra/1.3.5 has taken the stage on 4567 for development with backup from WEBrick
[2013-03-07 23:57:40] INFO WEBrick::HTTPServer#start: pid=62610 port=4567
But when I go with a browser on localhost (port 4567), I have the following logs:
api.rb logs
127.0.0.1 - - [07/Mar/2013 23:57:46] "OPTIONS /hi HTTP/1.1" 404 442 0.0015
localhost - - [07/Mar/2013:23:57:46 CET] "OPTIONS /hi HTTP/1.1" 404 442
http://localhost:4567/ -> /hi
client.rb logs
127.0.0.1 - - [07/Mar/2013 23:57:46] "GET / HTTP/1.1" 304 - 0.0093
localhost - - [07/Mar/2013:23:57:46 CET] "GET / HTTP/1.1" 304 0
- -> /
I did a lot a search about Cross-origin resource sharing and I tested many different ways. I currently have no idea how to process. Thank you for any help.
Edit:
My problem is that, the api.rb server return an error 404 after the AngularJS call. Moreover, there is two OPTIONS /hi requests, which is weird. I think it's a CORS symptom, but I added some header in order to accept cross-origin queries.
Instead of this, the server should return a 200 with the JSON. I really don't see how to fix it.

I had to add the following to my sinatra app to get it to work with CORS and angular:
options "*" do
response.headers["Allow"] = "HEAD,GET,PUT,DELETE,OPTIONS"
# Needed for AngularJS
response.headers["Access-Control-Allow-Headers"] = "X-Requested-With, X-HTTP-Method-Override, Content-Type, Cache-Control, Accept"
halt HTTP_STATUS_OK
end
I also used sinatra-cross_origin, but you might not need that seeing as you set the headers manually.

Related

Rails 7 connect to Twitter API strict-origin-when-cross-origin error

Context: attempting to connect to twitter API Oauth2 version, after submitting twice, both with and without the following block initializers/content_security_policy.rb
Rails.application.configure do
config.content_security_policy do |policy|
policy.default_src :self, :https
policy.font_src :self, :https, :data
policy.img_src :self, :https, :data
policy.object_src :none
policy.script_src :self, :https
policy.style_src :self, :https
# # Specify URI for violation reports
# # policy.report_uri "/csp-violation-report-endpoint"
end
end
via the following rendered rails code to HTML form
<%= form_tag('/auth/twitter2', method: 'post', data: {turbo: false}) do %>
<button type='submit'>Login with Twitter</button>
<% end %>
<form data-turbo="false" action="/auth/twitter2" accept-charset="UTF-8" method="post"><input type="hidden" name="authenticity_token" value="mU-GNjvKcWumrWZME_EszVTvi5wxo_5si89wOyCzCM0_SOmjAWQp1Vb8Gey71T1vCkRE9hahDd7r5zLpip1d_A" autocomplete="off">
<button type="submit">Login with Twitter</button>
</form>
The same was attempted with both a localhost:3000 host and an ngrok.io host
The console for the browser complains with the data at bottom.
Notes:
• the client ID is correct as set in the credentials
• the redirect_url has a slash removed from the string, yet it is present in the Twitter developer console https://https://170-343e-5-92-35.eu.ngrok.io/auth/twitter2/callback.eu.ngrok.io/auth/twitter2/callback
• twitter seems to recognize an active user x-twitter-active-user
It appears the API recognizes user but returns an error for lack of a security policy.
Yet something is wrong / missing here. What is it?
gems used are:
gem "omniauth", "~> 2.1"
gem "omniauth-rails_csrf_protection", "~> 1.0"
gem "omniauth-twitter2", "~> 0.1.0"
XHR GET https://twitter.com/i/api/2/oauth2/authorize?code_challenge=VqpkyR0-V1CTxnWXCdv0GCN_YP0fxX4JG0CggNxzDlo&code_challenge_method=S256&client_id=QkNaZGYxdXV2VVBteUhOZnZDZmQ6MTpjaQ&redirect_uri=https://170-343e-5-92-35.eu.ngrok.ioauth/twitter2/callback&response_type=code&scope=tweet.read users.read&state=274c1aa25c3274500095c77115cb4acc246fb9615e82f81a
[HTTP/2 400 Bad Request 187ms]
GET
scheme
https
host
twitter.com
filename
/i/api/2/oauth2/authorize
code_challenge
VqpkyR0-V1CTxnWXCdv0GCN_YP0fxX4JG0CggNxzDlo
code_challenge_method
S256
client_id
XV2VhQkNaZGYxdOZVBteUnZDZmQ6MTpjaQ
redirect_uri
https://170-343e-5-92-35.eu.ngrok.ioauth/twitter2/callback
response_type
code
scope
tweet.read users.read
state
274c1aa25c3274500095c77115cb4acc246fb9615e82f81a
Address
104.244.42.129:443
Status
400
Bad Request
Version HTTP/2
Transferred 706 B (132 B size)
Referrer Policy strict-origin-when-cross-origin
cache-control
no-cache, no-store, max-age=0
content-disposition
attachment; filename=json.json
content-encoding
gzip
content-length
128
content-type
application/json;charset=UTF-8
date
Mon, 31 Oct 2022 13:20:46 GMT
perf
7626143928
server
tsa_o
strict-transport-security
max-age=631138519
x-connection-hash
97ae1535e53b9ac87a0e6dc13996c3433bbbbaa470309893496090c60964af9d
x-content-type-options
nosniff
X-Firefox-Spdy
h2
x-frame-options
SAMEORIGIN
x-response-time
137
x-transaction-id
51c8c8c80424d52b
x-xss-protection
0
Accept
*/*
Accept-Encoding
gzip, deflate, br
Accept-Language
en-US,en;q=0.5
authorization
Bearer AAAAAAAAAAAAAAAAAAAAANRILgH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhAAAAAAnNwIzUejRCOuLTvJu4FA33AGWWjCpTnA
Connection
keep-alive
Cookie
guest_id=v1%3A165780214435378276; ct0=4020832aeed06194a4a62c8e5cc444311104716913ea7dcd10c30bb3dccfc87204d0ecf06771c5be6912634af55dd73edef992ae81eb79b1f507c8a79a50723aa018762a63ce9bca4aac58de0c35aedf; d_prefs=MjoxLGNvbnNlbnRfdmVyc2lvbjoyLHRleHRfdmVyc2lvbjoxMDAw; kdt=IZm9EbuU31Z5S5qEyVo0YPtSiIgF8djIWpHREbzq; twid=u%3D829665148143022080; auth_token=615b92f058b05ed8cd8829494d9421c5bb35a34a; night_mode=2; eu_cn=1; _twitter_sess=BAh7CyIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNo%250ASGFzaHsABjoKQHVzZWR7ADoPY3JlYXRlZF9hdGwrCPgH%252FvyBAToMY3NyZl9p%250AZCIlYmQ2YjVhYWNkYTYyZTQyYjI1YjEzNzkwYWM0MThmNWE6B2lkIiUyMjg0%250AZWZkZDMzZjcwMGU2NjVmMjhmNDY4Yzc3ZGI4NjofbGFzdF9wYXNzd29yZF9j%250Ab25maXJtYXRpb24iFTE2NjcyMDY2MjM0ODkwMDA6HnBhc3N3b3JkX2NvbmZp%250Acm1hdGlvbl91aWQiFzgyOTY2NTE0ODE0MzAyMjA4MA%253D%253D--bf686a94467ee3b422f132c9b1b181de4480d7e6; des_opt_in=N
DNT
1
Host
twitter.com
Referer
https://twitter.com/i/oauth2/authorize?client_id=QkNaZGYxdXV2VVBteUhOZnZDZmQ6MTpjaQ&code_challenge=VqpkyR0-V1CTxnWXCdv0GCN_YP0fxX4JG0CggNxzDlo&code_challenge_method=S256&redirect_uri=https%3A%2F%2F170-343e-5-92-35.eu.ngrok.ioauth%2Ftwitter2%2Fcallback&response_type=code&scope=tweet.read+users.read&state=274c1aa25c3274500095c77115cb4acc246fb9615e82f81a
Sec-Fetch-Dest
empty
Sec-Fetch-Mode
cors
Sec-Fetch-Site
same-origin
TE
trailers
User-Agent
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:106.0) Gecko/20100101 Firefox/106.0
x-csrf-token
4020832aeed06194a4a62c8e5cc444311104716913ea7dcd10c30bb3dccfc87204d0ecf06771c5be6912634af55dd73edef992ae81eb79b1f507c8a79a50723aa018762a63ce9bca4aac58de0c35aedf
x-twitter-active-user
yes
x-twitter-auth-type
OAuth2Session
x-twitter-client-language
en
There was another gem involved: Devise
Although config/initializers/devise.rb did not include any references to
config.omniauth :twitter2 it still conflicted with the omniauth gem.
Removing omniauth was necessary, in addition to configuring the devise initializer, to properly connect with twitter provider (exactly twitter2 for OAuth 2.0 connections).

ZAP Passive scan rules are part of scan even after disabing them

I am using ZAP docker image to perform API scans. I have disabled some passive scan rules in zap_started hook python script. Still, these are listed as part of the final report.
Script to disable passive scan rules:
pscan_id_list = [10003, 10015, 10017, 10020, 10021, 10028, 10029, 10031, 10032, 10039, 10040, 10041, 10041, 10043, 10052, 10050, 10056, 10061, 10108, 10109, 90001, 90026, 90029, 90030]
for pscan_id in pscan_id_list:
zap.pscan.set_scanner_alert_threshold(id=pscan_id, alertthreshold='OFF')
Logs confirm rules are disabled:
2021-06-17 06:44:10,269 Starting new HTTP connection (1): localhost:51008
2021-06-17 06:44:10,281 http://localhost:51008 "GET http://zap/JSON/pscan/action/setScannerAlertThreshold/?id=10003&alertThreshold=OFF&apikey= HTTP/1.1" 200 15
2021-06-17 06:44:10,288 Starting new HTTP connection (1): localhost:51008
2021-06-17 06:44:10,298 http://localhost:51008 "GET http://zap/JSON/pscan/action/setScannerAlertThreshold/?id=10015&alertThreshold=OFF&apikey= HTTP/1.1" 200 15
2021-06-17 06:44:10,304 Starting new HTTP connection (1): localhost:51008
2021-06-17 06:44:10,313 http://localhost:51008 "GET http://zap/JSON/pscan/action/setScannerAlertThreshold/?id=10017&alertThreshold=OFF&apikey= HTTP/1.1" 200 15
2021-06-17 06:44:10,320 Starting new HTTP connection (1): localhost:51008
2021-06-17 06:44:10,327 http://localhost:51008 "GET http://zap/JSON/pscan/action/setScannerAlertThreshold/?id=10020&alertThreshold=OFF&apikey= HTTP/1.1" 200 15
2021-06-17 06:44:10,333 Starting new HTTP connection (1): localhost:51008
2021-06-17 06:44:10,343 http://localhost:51008 "GET http://zap/JSON/pscan/action/setScannerAlertThreshold/?id=10021&alertThreshold=OFF&apikey= HTTP/1.1" 200 15
2021-06-17 06:44:10,350 Starting new HTTP connection (1): localhost:51008
2021-06-17 06:44:10,361 http://localhost:51008 "GET http://zap/JSON/pscan/action/setScannerAlertThreshold/?id=10028&alertThreshold=OFF&apikey= HTTP/1.1" 200 15
Passive scan rules are still listed in final report:
PASS: Vulnerable JS Library [10003]
PASS: Cookie No HttpOnly Flag [10010]
PASS: Cookie Without Secure Flag [10011]
PASS: Incomplete or No Cache-control and Pragma HTTP Header Set [10015]
PASS: Cross-Domain JavaScript Source File Inclusion [10017]
PASS: Content-Type Header Missing [10019]
PASS: X-Frame-Options Header [10020]
PASS: X-Content-Type-Options Header Missing [10021]
PASS: Information Disclosure - Sensitive Information in URL [10024]
PASS: Information Disclosure - Sensitive Information in HTTP Referrer Header [10025]
PASS: HTTP Parameter Override [10026]
PASS: Information Disclosure - Suspicious Comments [10027]
PASS: Open Redirect [10028]
PASS: Cookie Poisoning [10029]
PASS: User Controllable Charset [10030]
PASS: User Controllable HTML Element Attribute (Potential XSS) [10031]
Try using alertThreshold='OFF' (capital T) as per https://www.zaproxy.org/docs/api/#pscanactionsetscanneralertthreshold

Unable to retrieve private release asset from Github using ansible

I'm trying to automatically download a release asset using ansible, but I receive a 400 "Invalid Argument error":
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>InvalidArgument</Code>
<Message>
Only one auth mechanism allowed;
only the X-Amz-Algorithm query parameter, Signature query string parameter
or the Authorization header should be specified
</Message>
<ArgumentName>Authorization</ArgumentName>
<ArgumentValue>Basic XXX</ArgumentValue>
<RequestId>XXXX</RequestId>
<HostId>XXXX</HostId>
</Error>
I have found a corresponding issue on GitHub, but I can't implement the solution using ansible without writing a custom script. My curremt code is:
- name: Download build asset
uri:
url: "{{ asset_url }}"
user: "{{ github_username }}"
password: "{{ github_token }}"
force_basic_auth: yes
headers:
Accept: application/octet-stream
I have also tried passing no headers and using the token in the url
- name: Download build asset
uri:
url: "https://{{ TOKEN }}:#api.github.com/repos/<ORG>/<REPO>/releases/assets/{{ ASSET_ID }}"
headers:
Accept: application/octet-stream
But then I receive an error 404 "Not found" Error (presumably because the authentication did not work (private URL parameters replaced as ):
fatal: [XXX]: FAILED! => changed=false
access_control_allow_origin: '*'
access_control_expose_headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset
connection: close
content: '{"message":"Not Found","documentation_url":"https://docs.github.com/rest/reference/repos#get-a-release-asset"}'
content_length: '110'
content_security_policy: default-src 'none'
content_type: application/json; charset=utf-8
date: Wed, 18 Nov 2020 15:45:42 GMT
elapsed: 0
json:
documentation_url: https://docs.github.com/rest/reference/repos#get-a-release-asset
message: Not Found
msg: 'Status code was 404 and not [200]: HTTP Error 404: Not Found'
redirected: false
referrer_policy: origin-when-cross-origin, strict-origin-when-cross-origin
server: GitHub.com
status: 404
strict_transport_security: max-age=31536000; includeSubdomains; preload
url: https://<TOKEN>#api.github.com/repos/<ORG>/<REPO>/releases/assets/28089234
vary: Accept-Encoding, Accept, X-Requested-With
x_content_type_options: nosniff
x_frame_options: deny
x_github_media_type: unknown
x_github_request_id: CC26:2942:15E1154:1948AE9:5FB541A6
x_ratelimit_limit: '60'
x_ratelimit_remaining: '58'
x_ratelimit_reset: '1605717756'
x_ratelimit_used: '2'
x_xss_protection: 1; mode=block
This only happens for release assets, other api calls work just fine using the basic auth method. It also works fine with the same request using curl or postman. Scopes for the Personal Access Token I use are:
repo (full access)
workflow
write:packages
read:packages
Update
For now sending the request using curl works, but I would prefer using the uri module:
name: Download build asset
shell: >
curl -J -L -H "Accept: application/octet-stream"
"https://{{ TOKEN }}#api.github.com/repos/<ORG>/<REPO>/releases/assets/{{ ASSET_ID }}"
--output "/tmp/asset.tar.gz"

Remote Debug API entrypoint with Codeception on PhpStorm

I'm trying to debug an application that is using docker [docker-compose], PhpStorm and Codeception. Xdebug's setup seems correct because if I add some breakpoint on the code then use the browser I'm able to stop on the breakpoint and debug the code with no issues. Also, Codeception setup seems correct because I'm able to debug the scenario placing some breakpoint in the ControllerCest file.
The issue here is when I'm trying to debug a breakpoint that is on the application controller from the Codeception ControllerCest file through $I->sendGet(self::SERVICE_URL), it doesn't stop on the selected breakpoint.
This is my api.suite.yml
modules:
enabled:
- REST:
url: 'http://app.local/api/v1/'
depends: PhpBrowser
part: Json
timeout: 1000
- PhpBrowser:
url: 'http://app.local/api/v1/'
headers:
Accept: application/json
Content-Type: application/json
Cookie: XDEBUG_SESSION=PHPSTORM
curl:
CURLOPT_RETURNTRANSFER: true
CURLOPT_TIMEOUT: 10000
- Symfony:
app_path: 'src'
environment: 'test'
- Doctrine2:
depends: Symfony
cleanup: true
- \App\Tests\Helper\Api
- Asserts

already initialized constant, and required twice

Hi, all,
i think this is a bug about the constant defined in sinatra, let's look my code.
route.rb
require 'sinatra'
get '/' do
C = "this is a test for constant"
"Hello World!"
end
Gemfile
source 'http://rubygems.org'
gem 'rack'
gem 'sinatra'
config.ru
require './route'
run Sinatra::Application
Starting the web server, we will see the below
$ rackup
[2011-10-08 19:54:36] INFO WEBrick 1.3.1
[2011-10-08 19:54:36] INFO ruby 1.9.2 (2011-07-09) [i686-linux]
[2011-10-08 19:54:36] INFO WEBrick::HTTPServer#start: pid=3268 port=9292
127.0.0.1 - - [08/Oct/2011 19:54:42] "GET / HTTP/1.1" 200 25 0.0059
127.0.0.1 - - [08/Oct/2011 19:54:42] "GET / HTTP/1.1" 200 25 0.0142
/home/zcdny/repo/test/route.rb:4: warning: already initialized constant C
127.0.0.1 - - [08/Oct/2011 19:54:43] "GET / HTTP/1.1" 200 25 0.0094
127.0.0.1 - - [08/Oct/2011 19:54:43] "GET / HTTP/1.1" 200 25 0.0098
/home/zcdny/repo/test/route.rb:4: warning: already initialized constant C
127.0.0.1 - - [08/Oct/2011 19:54:55] "GET / HTTP/1.1" 200 25 0.0003
127.0.0.1 - - [08/Oct/2011 19:54:55] "GET / HTTP/1.1" 200 25 0.0006
/home/zcdny/repo/test/route.rb:4: warning: already initialized constant C
127.0.0.1 - - [08/Oct/2011 19:54:56] "GET / HTTP/1.1" 200 25 0.0003
127.0.0.1 - - [08/Oct/2011 19:54:56] "GET / HTTP/1.1" 200 25 0.0005
Eidt
Fixing the file route.rb
require 'sinatra'
configure do
C = "this is a test for constant"
end
get '/' do
"Hello World!"
end
Now, the server no longer warning the constant be initialized.
But the log of server still appears double 'GET' require ,
i just want it requires for one to every client required, that is my question, How to solve it.
Thanks in advance.
What's wrong about that? If you define the constant twice (which happens if you have two GET requests or a GET and a HEAD request) then that warning will be displayed. You global variables instead. But if you don't have to, try to avoid global state at all cost, otherwise you might run in architectural issues (what if you want to serve more endpoints and globals clash) and make it hard to scale: if you rely on the internal state of a process, will you be able to serve the website from two processes? what about two machines?