Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added nonce support #86

Merged
merged 6 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

To use phraseapp-in-context-editor-ruby with your application you have to:

* Sign up for a Phrase account: [https://app.phrase.com/signup](https://app.phrase.com/signup)
* Use the excellent [i18n](https://github.com/ruby-i18n/i18n) gem also used by [Rails](https://guides.rubyonrails.org/i18n.html)
- Sign up for a Phrase account: [https://app.phrase.com/signup](https://app.phrase.com/signup)
- Use the excellent [i18n](https://github.com/ruby-i18n/i18n) gem also used by [Rails](https://guides.rubyonrails.org/i18n.html)

### Demo

Expand All @@ -21,11 +21,13 @@ Login via the demo credentials `[email protected]` / `phrase`
### Installation

#### NOTE: You can not use the old version of the ICE with integration versions of >2.0.0, you have to instead use 1.x.x versions as before

#### via Gem

```bash
gem install phraseapp-in-context-editor-ruby
```

#### via Bundler

Add it to your `Gemfile`
Expand Down Expand Up @@ -84,13 +86,26 @@ Old version of the ICE is not available since version 2.0.0. If you still would
#### Using the US Datacenter with ICE

In addition to the settings in your `config/initializers/phraseapp_in_context_editor.rb`, set the US datacenter to enable the ICE to work with the US endpoints.

```ruby
config.enabled = true
config.project_id = "YOUR_PROJECT_ID"
config.account_id = "YOUR_ACCOUNT_ID"
config.datacenter = "us"
```

#### Using with CSP

The script will automatically get the nonce from `content_security_policy_nonce`
The content_security_policy.rb has to have `:strict_dynamic` for `policy.script_src` since we are loading more scripts dynamically because of our way of deploying

```ruby
policy.script_src :self, :https, :strict_dynamic
policy.style_src :self, :https
```

The `config.content_security_policy_nonce_directives = %w[script-src style-src]` can include `style-src` but this _might_ break some styling in some cases

### Browser support

This library might not work out of the box for some older browser or IE11. We recommend to add [Babel](https://github.com/babel/babel) to the build pipeline if those browser need to be supported.
Expand Down
2 changes: 1 addition & 1 deletion examples/demo/app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<%= csrf_meta_tags %>
<%= csp_meta_tag %>

<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload", nonce: true %>
<%= javascript_importmap_tags %>
<%= load_in_context_editor %>
</head>
Expand Down
38 changes: 19 additions & 19 deletions examples/demo/config/initializers/content_security_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@
# See the Securing Rails Applications Guide for more information:
# https://guides.rubyonrails.org/security.html#content-security-policy-header

# 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
#
# # Generate session nonces for permitted importmap and inline scripts
# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
# config.content_security_policy_nonce_directives = %w(script-src)
#
# # Report violations without enforcing the policy.
# # config.content_security_policy_report_only = true
# end
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, :strict_dynamic
policy.style_src :self, :https
# Specify URI for violation reports
# policy.report_uri "/csp-violation-report-endpoint"
end

# Generate session nonces for permitted importmap and inline scripts
config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
config.content_security_policy_nonce_directives = %w[script-src style-src]

# Report violations without enforcing the policy.
# config.content_security_policy_report_only = true
end
2 changes: 1 addition & 1 deletion lib/phraseapp-in-context-editor-ruby/view_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def load_in_context_editor(opts = {})
}.merge(opts)

snippet = <<-EOS
<script>
<script nonce='#{content_security_policy_nonce}'>
window.PHRASEAPP_CONFIG = #{configuration.to_json};
(function() {
let phraseapp = document.createElement('script');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
require "phraseapp-in-context-editor-ruby"
require "phraseapp-in-context-editor-ruby/view_helpers"

def content_security_policy_nonce
"some_nonce"
end

describe PhraseApp::InContextEditor::ViewHelpers do
before(:all) do
class Helpers
Expand All @@ -20,7 +24,7 @@ class Helpers
before(:each) { PhraseApp::InContextEditor.config.enabled = true }

describe "has right ICE bundle address" do
it { is_expected.to include("<script>") }
it { is_expected.to include("<script nonce='some_nonce'>") }
it { is_expected.to include("https://d2bgdldl6xit7z.cloudfront.net/latest/ice/index.js") }
it { is_expected.to include("</script>") }
end
Expand Down
Loading