diff --git a/.coditsu/ci.yml b/.coditsu/ci.yml new file mode 100644 index 0000000..dff43e8 --- /dev/null +++ b/.coditsu/ci.yml @@ -0,0 +1,3 @@ +repository_id: 'f789891f-3f4e-42be-a25b-068d49708ddb' +api_key: <%= ENV['CODITSU_API_KEY'] %> +api_secret: <%= ENV['CODITSU_API_SECRET'] %> diff --git a/.gitignore b/.gitignore index b6a0a6d..c3c5c77 100644 --- a/.gitignore +++ b/.gitignore @@ -30,4 +30,6 @@ .rvmrc # Example files -/example/.bundle \ No newline at end of file +/example/.bundle +vendor +.coditsu/local.yml diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..ac31b24 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,15 @@ +Documentation: + Enabled: false +AllCops: + TargetRubyVersion: 2.6 + +Metrics/LineLength: + Max: 100 + +Metrics/ModuleLength: + Exclude: + - "**/*_spec.rb" + +Metrics/BlockLength: + Exclude: + - "**/*_spec.rb" diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..57cf282 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +2.6.5 diff --git a/.travis.yml b/.travis.yml index 9e4c0dd..14d4699 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,47 @@ -language: ruby -rvm: - - 2.0.0 - - 2.1.8 - - 2.2.4 - - 2.3.0 +services: + - docker + +dist: trusty +sudo: false +cache: bundler + +git: + depth: false + +test: &test + stage: test + language: ruby + before_install: + - gem install bundler + - gem update --system + +jobs: + include: + - <<: *test + rvm: 2.6.5 + - <<: *test + rvm: 2.5.7 + - <<: *test + rvm: 2.4.8 + + - stage: coditsu + language: ruby + rvm: 2.6.3 + before_install: + - gem update --system + - gem install bundler + before_script: + - docker create -v /sources --name sources alpine:3.4 /bin/true + - docker cp ./ sources:/sources + script: > + docker run + -e CODITSU_API_KEY + -e CODITSU_API_SECRET + -e CODITSU_REPOSITORY_ID + -e CODITSU_BUILD_BRANCH=$TRAVIS_BRANCH + --volumes-from sources + coditsu/build-runner:latest + +stages: + - test + - coditsu diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..5de477a --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,6 @@ +## master +- [#58](https://github.com/castle/ruby-u2f/pull/58) drop support for ruby 2.3 +- [#41](https://github.com/castle/ruby-u2f/pull/41) drop support for ruby 2.2 + +## 1.0.0 (2016-02-18) +- update ruby-u2f to work with the v1.1 U2F JavaScript API. diff --git a/Gemfile b/Gemfile index 3be9c3c..c88b5df 100644 --- a/Gemfile +++ b/Gemfile @@ -1,2 +1,13 @@ -source "https://rubygems.org" +# frozen_string_literal: true + +source 'https://rubygems.org' gemspec + +gem 'rake' + +group :test do + gem 'coveralls_reborn' + gem 'json_expressions' + gem 'rspec' + gem 'simplecov' +end diff --git a/Gemfile.lock b/Gemfile.lock index ddfb09b..5913015 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,85 +1,54 @@ PATH remote: . specs: - u2f (0.2.1) + u2f (1.0.0) GEM remote: https://rubygems.org/ specs: - ast (2.0.0) - astrolabe (1.3.0) - parser (>= 2.2.0.pre.3, < 3.0) - coveralls (0.8.10) - json (~> 1.8) - rest-client (>= 1.6.8, < 2) - simplecov (~> 0.11.0) - term-ansicolor (~> 1.3) - thor (~> 0.19.1) - tins (~> 1.6.0) - diff-lcs (1.2.5) - docile (1.1.5) - domain_name (0.5.25) - unf (>= 0.0.5, < 1.0.0) - http-cookie (1.0.2) - domain_name (~> 0.5) - json (1.8.3) - json_expressions (0.8.3) - mime-types (2.99) - netrc (0.11.0) - parser (2.2.0.pre.7) - ast (>= 1.1, < 3.0) - slop (~> 3.4, >= 3.4.5) - powerpack (0.0.9) - rainbow (2.0.0) - rake (10.3.2) - rest-client (1.8.0) - http-cookie (>= 1.0.2, < 2.0) - mime-types (>= 1.16, < 3.0) - netrc (~> 0.7) - rspec (3.1.0) - rspec-core (~> 3.1.0) - rspec-expectations (~> 3.1.0) - rspec-mocks (~> 3.1.0) - rspec-core (3.1.7) - rspec-support (~> 3.1.0) - rspec-expectations (3.1.2) + coveralls_reborn (0.16.0) + simplecov (~> 0.18.1) + term-ansicolor (~> 1.6) + thor (>= 0.20.3, < 2.0) + tins (~> 1.16) + diff-lcs (1.3) + docile (1.3.2) + json_expressions (0.9.0) + rake (13.0.1) + rspec (3.9.0) + rspec-core (~> 3.9.0) + rspec-expectations (~> 3.9.0) + rspec-mocks (~> 3.9.0) + rspec-core (3.9.2) + rspec-support (~> 3.9.3) + rspec-expectations (3.9.2) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.1.0) - rspec-mocks (3.1.3) - rspec-support (~> 3.1.0) - rspec-support (3.1.2) - rubocop (0.27.1) - astrolabe (~> 1.3) - parser (>= 2.2.0.pre.7, < 3.0) - powerpack (~> 0.0.6) - rainbow (>= 1.99.1, < 3.0) - ruby-progressbar (~> 1.4) - ruby-progressbar (1.7.0) - simplecov (0.11.1) - docile (~> 1.1.0) - json (~> 1.8) - simplecov-html (~> 0.10.0) - simplecov-html (0.10.0) - slop (3.6.0) - term-ansicolor (1.3.2) + rspec-support (~> 3.9.0) + rspec-mocks (3.9.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.9.0) + rspec-support (3.9.3) + simplecov (0.18.5) + docile (~> 1.1) + simplecov-html (~> 0.11) + simplecov-html (0.12.2) + sync (0.5.0) + term-ansicolor (1.7.1) tins (~> 1.0) - thor (0.19.1) - tins (1.6.0) - unf (0.1.4) - unf_ext - unf_ext (0.0.7.1) + thor (1.0.1) + tins (1.25.0) + sync PLATFORMS ruby DEPENDENCIES - coveralls (~> 0.8.10) - json_expressions (~> 0.8.3) - rake (~> 10.3) - rspec (~> 3.1) - rubocop (~> 0.27.1) - simplecov (~> 0.11.1) + coveralls_reborn + json_expressions + rake + rspec + simplecov u2f! BUNDLED WITH - 1.11.0 + 2.1.4 diff --git a/README.md b/README.md index 1a95f8c..326ae53 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,9 @@ # Ruby U2F -[![Gem Version](https://badge.fury.io/rb/u2f.png)](http://badge.fury.io/rb/u2f) -[![Dependency Status](https://gemnasium.com/castle/ruby-u2f.svg)](https://gemnasium.com/castle/ruby-u2f) +[![Gem Version](https://badge.fury.io/rb/u2f.svg)](https://badge.fury.io/rb/u2f) [![security](https://hakiri.io/github/castle/ruby-u2f/master.svg)](https://hakiri.io/github/castle/ruby-u2f/master) -[![Build Status](https://travis-ci.org/castle/ruby-u2f.png)](https://travis-ci.org/castle/ruby-u2f) +[![Build Status](https://travis-ci.org/castle/ruby-u2f.svg?branch=API_v1_1)](https://travis-ci.org/castle/ruby-u2f) [![Code Climate](https://codeclimate.com/github/castle/ruby-u2f/badges/gpa.svg)](https://codeclimate.com/github/castle/ruby-u2f) [![Coverage Status](https://img.shields.io/coveralls/castle/ruby-u2f.svg)](https://coveralls.io/r/castle/ruby-u2f) @@ -40,7 +39,9 @@ The U2F library has two major tasks: Each task starts by generating a challenge on the server, which is rendered to a web view, read by the browser APIs and transmitted to the plugged in U2F devices for verification. The U2F device responds and triggers a callback in the browser, and a form is posted back to your server where you verify the challenge and store the U2F device information to your database. -You'll need an instance of `U2F::U2F`, which is conveniently placed in an [instance method](https://github.com/castle/ruby-u2f/blob/master/example/app/helpers/helpers.rb) on the controller. The initializer takes an **App ID** as argument. +Note that ordinarily, each user will have one or more U2F registrations (as it's a common usage pattern for users to have more than one U2F device -- for example one for regular use, and a second stored safely as a backup). While it's omitted from examples here for brevity, a new registration should typically be associated with the particular user registering. Likewise, when authenticating, queries over "all registrations" should actually be scoped to registrations associated with the particular user being authenticated. + +You'll need an instance of `U2F::U2F`, which is conveniently placed in an [instance method](https://github.com/castle/ruby-u2f/blob/API_v1_1/example/app/helpers/helpers.rb) on the controller. The initializer takes an **App ID** as argument. ```ruby def u2f @@ -67,6 +68,8 @@ def new key_handles = Registration.map(&:key_handle) @sign_requests = u2f.authentication_requests(key_handles) + @app_id = u2f.app_id + render 'registrations/new' end ``` @@ -82,10 +85,11 @@ Render a form that will be automatically posted when the U2F device reponds. ```javascript // render requests from server into Javascript format -var registerRequests = <%= @registration_requests.as_json.to_json.html_safe %>; +var appId = <%= @app_id.to_json.html_safe %> +var registerRequests = <%= @registration_requests.to_json.html_safe %>; var signRequests = <%= @sign_requests.as_json.to_json.html_safe %>; -u2f.register(registerRequests, signRequests, function(registerResponse) { +u2f.register(appId, registerRequests, signRequests, function(registerResponse) { var form, reg; if (registerResponse.errorCode) { @@ -138,10 +142,12 @@ def new return 'Need to register first' if key_handles.empty? # Generate SignRequests + @app_id = u2f.app_id @sign_requests = u2f.authentication_requests(key_handles) + @challenge = u2f.challenge - # Store challenges. We need them for the verification step - session[:challenges] = @sign_requests.map(&:challenge) + # Store challenge. We need it for the verification step + session[:challenge] = @challenge render 'authentications/new' end @@ -158,9 +164,11 @@ Render a form that will be automatically posted when the U2F device reponds. ```javascript // render requests from server into Javascript format -var signRequests = <%= @sign_requests.as_json.to_json.html_safe %>; +var signRequests = <%= @sign_requests.to_json.html_safe %>; +var challenge = <%= @challenge.to_json.html_safe %>; +var appId = <%= @app_id.to_json.html_safe %>; -u2f.sign(signRequests, function(signResponse) { +u2f.sign(appId, challenge, signRequests, function(signResponse) { var form, reg; if (signResponse.errorCode) { @@ -187,13 +195,13 @@ def create return 'Need to register first' unless registration begin - u2f.authenticate!(session[:challenges], response, + u2f.authenticate!(session[:challenge], response, Base64.decode64(registration.public_key), registration.counter) rescue U2F::Error => e return "Unable to authenticate: <%= e.class.name %>" ensure - session.delete(:challenges) + session.delete(:challenge) end registration.update(counter: response.counter) diff --git a/Rakefile b/Rakefile index 5786e6a..25864e6 100644 --- a/Rakefile +++ b/Rakefile @@ -1,7 +1,9 @@ -require "bundler/gem_tasks" -require "rspec/core/rake_task" +# frozen_string_literal: true + +require 'bundler/gem_tasks' +require 'rspec/core/rake_task' RSpec::Core::RakeTask.new -task :default => :spec -task :test => :spec \ No newline at end of file +task default: :spec +task test: :spec diff --git a/example/Gemfile b/example/Gemfile index 73e40be..0d2042c 100644 --- a/example/Gemfile +++ b/example/Gemfile @@ -1,20 +1,25 @@ +# frozen_string_literal: true + source 'https://rubygems.org' # Project requirements gem 'rake' # Component requirements -gem 'haml' +gem 'dm-aggregates' +gem 'dm-constraints' +gem 'dm-core' +gem 'dm-migrations' gem 'dm-sqlite-adapter' -gem 'dm-validations' gem 'dm-timestamps' -gem 'dm-migrations' -gem 'dm-constraints' -gem 'dm-aggregates' gem 'dm-types' -gem 'dm-core' +gem 'dm-validations' +gem 'haml' # Padrino Stable Gem -gem 'padrino', '0.12.4' +gem 'padrino' + +# To enable https +gem 'thin' -gem 'u2f'#, path: '../.' +gem 'u2f', '1.0.0' diff --git a/example/Gemfile.lock b/example/Gemfile.lock index 227ba34..7e44068 100644 --- a/example/Gemfile.lock +++ b/example/Gemfile.lock @@ -1,18 +1,16 @@ GEM remote: https://rubygems.org/ specs: - activesupport (4.1.7) - i18n (~> 0.6, >= 0.6.9) - json (~> 1.7, >= 1.7.7) - minitest (~> 5.1) - thread_safe (~> 0.1) - tzinfo (~> 1.1) - addressable (2.3.6) - bcrypt (3.1.9) + addressable (2.8.1) + public_suffix (>= 2.0.2, < 6.0) + bcrypt (3.1.18) bcrypt-ruby (3.1.5) bcrypt (>= 3.1.3) - data_objects (0.10.14) + concurrent-ruby (1.2.2) + daemons (1.2.6) + data_objects (0.10.17) addressable (~> 2.1) + date (3.3.3) dm-aggregates (1.2.0) dm-core (~> 1.2.0) dm-constraints (1.2.0) @@ -39,79 +37,89 @@ GEM uuidtools (~> 2.1) dm-validations (1.2.0) dm-core (~> 1.2.0) - do_sqlite3 (0.10.14) - data_objects (= 0.10.14) + do_sqlite3 (0.10.17) + data_objects (= 0.10.17) + eventmachine (1.2.7) fastercsv (1.5.5) - haml (4.0.5) + haml (5.0.4) + temple (>= 0.8.0) tilt - http_router (0.11.1) - rack (>= 1.0.0) - url_mount (~> 0.2.1) - i18n (0.6.11) - json (1.8.1) - mail (2.5.4) - mime-types (~> 1.16) - treetop (~> 1.4.8) - mime-types (1.25.1) - minitest (5.4.2) - moneta (0.7.20) - multi_json (1.10.1) - padrino (0.12.4) - padrino-admin (= 0.12.4) - padrino-cache (= 0.12.4) - padrino-core (= 0.12.4) - padrino-gen (= 0.12.4) - padrino-helpers (= 0.12.4) - padrino-mailer (= 0.12.4) - padrino-support (= 0.12.4) - padrino-admin (0.12.4) - padrino-core (= 0.12.4) - padrino-helpers (= 0.12.4) - padrino-cache (0.12.4) - moneta (~> 0.7.0) - padrino-core (= 0.12.4) - padrino-helpers (= 0.12.4) - padrino-core (0.12.4) - activesupport (>= 3.1) - http_router (~> 0.11.0) - padrino-support (= 0.12.4) - rack-protection (>= 1.5.0) - sinatra (~> 1.4.2) - thor (~> 0.18) - padrino-gen (0.12.4) - bundler (~> 1.0) - padrino-core (= 0.12.4) - padrino-helpers (0.12.4) - i18n (~> 0.6, >= 0.6.7) - padrino-support (= 0.12.4) - tilt (~> 1.4.1) - padrino-mailer (0.12.4) - mail (~> 2.5.3) - padrino-core (= 0.12.4) - padrino-support (0.12.4) - activesupport (>= 3.1) - polyglot (0.3.5) - rack (1.5.2) - rack-protection (1.5.3) + i18n (0.9.5) + concurrent-ruby (~> 1.0) + json (1.8.6) + mail (2.8.1) + mini_mime (>= 0.1.1) + net-imap + net-pop + net-smtp + mime-types (2.99.3) + mini_mime (1.1.2) + moneta (1.1.1) + multi_json (1.15.0) + mustermann (2.0.2) + ruby2_keywords (~> 0.0.1) + net-imap (0.3.4) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.1) + timeout + net-smtp (0.3.3) + net-protocol + padrino (0.15.3) + padrino-admin (= 0.15.3) + padrino-cache (= 0.15.3) + padrino-core (= 0.15.3) + padrino-gen (= 0.15.3) + padrino-helpers (= 0.15.3) + padrino-mailer (= 0.15.3) + padrino-support (= 0.15.3) + padrino-admin (0.15.3) + padrino-core (= 0.15.3) + padrino-helpers (= 0.15.3) + padrino-cache (0.15.3) + moneta (~> 1.1.0) + padrino-core (= 0.15.3) + padrino-helpers (= 0.15.3) + padrino-core (0.15.3) + padrino-support (= 0.15.3) + sinatra (>= 2.2.4) + thor (~> 1.0) + padrino-gen (0.15.3) + bundler (>= 1.0, < 3) + padrino-core (= 0.15.3) + padrino-helpers (0.15.3) + i18n (>= 0.6.7, < 2) + padrino-support (= 0.15.3) + tilt (>= 1.4.1, < 3) + padrino-mailer (0.15.3) + mail (~> 2.5) + mime-types (< 4) + padrino-core (= 0.15.3) + padrino-support (0.15.3) + public_suffix (5.0.1) + rack (2.2.9) + rack-protection (2.2.4) rack - rake (10.3.2) - sinatra (1.4.5) - rack (~> 1.4) - rack-protection (~> 1.4) - tilt (~> 1.3, >= 1.3.4) + rake (12.3.3) + ruby2_keywords (0.0.5) + sinatra (2.2.4) + mustermann (~> 2.0) + rack (~> 2.2) + rack-protection (= 2.2.4) + tilt (~> 2.0) stringex (1.5.1) - thor (0.19.1) - thread_safe (0.3.4) - tilt (1.4.1) - treetop (1.4.15) - polyglot - polyglot (>= 0.3.1) - tzinfo (1.2.2) - thread_safe (~> 0.1) - u2f (0.2.0) - url_mount (0.2.1) - rack - uuidtools (2.1.5) + temple (0.8.0) + thin (1.7.2) + daemons (~> 1.0, >= 1.0.9) + eventmachine (~> 1.0, >= 1.0.4) + rack (>= 1, < 3) + thor (1.2.1) + tilt (2.1.0) + timeout (0.3.2) + u2f (1.0.0) + uuidtools (2.2.0) PLATFORMS ruby @@ -126,6 +134,10 @@ DEPENDENCIES dm-types dm-validations haml - padrino (= 0.12.4) + padrino rake - u2f + thin + u2f (= 1.0.0) + +BUNDLED WITH + 1.16.3 diff --git a/example/README.md b/example/README.md index f0b8d23..2e6271c 100644 --- a/example/README.md +++ b/example/README.md @@ -1,5 +1,5 @@ ```bash bundle install padrino rake db:migrate -padrino start +thin start --ssl-disable-verify ``` diff --git a/example/Rakefile b/example/Rakefile index 98c59df..42ac015 100644 --- a/example/Rakefile +++ b/example/Rakefile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'bundler/setup' require 'padrino-core/cli/rake' diff --git a/example/app/app.rb b/example/app/app.rb index 41befd0..7a3f5f8 100644 --- a/example/app/app.rb +++ b/example/app/app.rb @@ -1,9 +1,11 @@ +# frozen_string_literal: true + module U2FExample class App < Padrino::Application register Padrino::Helpers enable :sessions - get "/" do + get '/' do render 'index' end end diff --git a/example/app/controllers/authentications.rb b/example/app/controllers/authentications.rb index de76458..7be566a 100644 --- a/example/app/controllers/authentications.rb +++ b/example/app/controllers/authentications.rb @@ -1,11 +1,15 @@ +# frozen_string_literal: true + require 'base64' U2FExample::App.controllers :authentications do get :new do key_handles = Registration.map(&:key_handle) return 'Need to register first' if key_handles.empty? + @app_id = u2f.app_id @sign_requests = u2f.authentication_requests(key_handles) - session[:challenges] = @sign_requests.map(&:challenge) + @challenge = u2f.challenge + session[:u2f_challenge] = @challenge render 'authentications/new' end @@ -17,13 +21,13 @@ return 'Need to register first' unless registration begin - u2f.authenticate!(session[:challenges], response, + u2f.authenticate!(session[:u2f_challenge], response, Base64.decode64(registration.public_key), registration.counter) rescue U2F::Error => e @error_message = "Unable to authenticate: #{e.class.name}" ensure - session.delete(:challenges) + session.delete(:u2f_challenge) end registration.update(counter: response.counter) diff --git a/example/app/controllers/registrations.rb b/example/app/controllers/registrations.rb index 67b0f49..0492654 100644 --- a/example/app/controllers/registrations.rb +++ b/example/app/controllers/registrations.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + U2FExample::App.controllers :registrations do get :new do @registration_requests = u2f.registration_requests @@ -6,25 +8,29 @@ key_handles = Registration.map(&:key_handle) @sign_requests = u2f.authentication_requests(key_handles) + @app_id = u2f.app_id + render 'registrations/new' end post :index do response = U2F::RegisterResponse.load_from_json(params[:response]) - reg = begin - u2f.register!(session[:challenges], response) + begin + reg = u2f.register!(session[:challenges], response) + + Registration.create!( + certificate: reg.certificate, + key_handle: reg.key_handle, + public_key: reg.public_key, + counter: reg.counter + ) rescue U2F::Error => e @error_message = "Unable to register: #{e.class.name}" ensure session.delete(:challenges) end - Registration.create!(certificate: reg.certificate, - key_handle: reg.key_handle, - public_key: reg.public_key, - counter: reg.counter) - render 'authentications/show' end end diff --git a/example/app/helpers/helpers.rb b/example/app/helpers/helpers.rb index 5d30d11..849fb4e 100644 --- a/example/app/helpers/helpers.rb +++ b/example/app/helpers/helpers.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + U2FExample::App.helpers do def u2f # use base_url as app_id, e.g. 'http://localhost:3000' diff --git a/example/app/views/authentications/new.haml b/example/app/views/authentications/new.haml index ebac786..61cabf7 100644 --- a/example/app/views/authentications/new.haml +++ b/example/app/views/authentications/new.haml @@ -19,6 +19,8 @@ :javascript var signRequests = #{@sign_requests.to_json.html_safe}; + var challenge = #{@challenge.to_json.html_safe}; + var appId = #{@app_id.to_json.html_safe}; var $waiting = document.getElementById('waiting'); var $error = document.getElementById('error'); var errorMap = { @@ -34,7 +36,7 @@ $error.innerHTML = errorMap[code]; }; - u2f.sign(signRequests, function(signResponse) { + u2f.sign(appId, challenge, signRequests, function(signResponse) { var form, reg; if (signResponse.errorCode) { diff --git a/example/app/views/authentications/show.haml b/example/app/views/authentications/show.haml index 806ddfc..180695f 100644 --- a/example/app/views/authentications/show.haml +++ b/example/app/views/authentications/show.haml @@ -10,4 +10,4 @@ .col-md-4.col-md-offset-4.text-center %hr %p - %a{:href => '/'} « Back to main page \ No newline at end of file + %a{:href => '/'} « Back to main page diff --git a/example/app/views/index.haml b/example/app/views/index.haml index 0f1bdea..d6cbcc6 100644 --- a/example/app/views/index.haml +++ b/example/app/views/index.haml @@ -6,4 +6,4 @@ %p.lead Welcome to the demo implementation of a U2F validation server in Ruby/Padrino. %a.btn.btn-default.btn-block.btn-lg{:href => 'registrations/new'} Register a new key - %a.btn.btn-default.btn-block.btn-lg{:href => 'authentications/new'} Validate a registered key \ No newline at end of file + %a.btn.btn-default.btn-block.btn-lg{:href => 'authentications/new'} Validate a registered key diff --git a/example/app/views/layouts/application.html.erb b/example/app/views/layouts/application.html.erb index aab2f88..27f0dfa 100644 --- a/example/app/views/layouts/application.html.erb +++ b/example/app/views/layouts/application.html.erb @@ -11,12 +11,12 @@ <%= stylesheet_link_tag '//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css' %> - + - <%= javascript_include_tag 'application' %> + <%= javascript_include_tag 'u2f-api' %>