nulogy_sso 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6cdaf701ea9f2d60f83b4997b098083962e749961bcf5333f7233b0d50c7020e
4
- data.tar.gz: 85da856cc70b327a5510484e59f4a8c61b243dd7083ef52b76a6c46f2e27ecb9
3
+ metadata.gz: 025625d2b1b251f2687e574aeebf1739c94ae6a672580f05164ba7e558ba5fdf
4
+ data.tar.gz: a987372dba2b6fd08ca877118e024e3e7a10eb16f34cac995d8f493c837dbaaa
5
5
  SHA512:
6
- metadata.gz: b4e3869377c7f1e3f628de5afb6d15ab365daa7b1bc0da8152efe165a809af0ec360abde1c44dbc9c68bef4c5002f27557809fb0e22634d677e19f6e5ab6a452
7
- data.tar.gz: 4b0b29196feb44b86d1b6a67e86c06660d4f9ae27563397a0633bb6e4bf5f47ce93050e2c75a98981fade342266c71b894cab789dd5febff678c2a53338d6a6b
6
+ metadata.gz: 3481d3605b625db5259b08a210932fac512cf45c7d4a4751c8d41e5229044c44711e53eb083693cd4b8c424579c0609c816eba8299fd07acacef82ab90e786fd
7
+ data.tar.gz: 54008fdb8cfb1fcfa350cd51f00865f09603517feeb33952fc7032f9f90a63b3aa20c73da19e5703fe7132a155d0dedc705927609a8820cf221755762d98cacb
data/README.md CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  [![Gem](https://img.shields.io/gem/v/nulogy_sso?label=nulogy_sso)](https://rubygems.org/gems/nulogy_sso "View this project in Rubygems")
4
4
 
5
+ ## Auth0
6
+ For more information on Auth0 see the [Auth0 documentation](https://auth0.com/docs/flows/concepts/auth-code#how-it-works).
7
+
5
8
  ## Installation
6
9
 
7
10
  This gem is a Rails Engine. It follows best practices [documented here](https://guides.rubyonrails.org/engines.html).
@@ -28,7 +31,31 @@ get "login", to: redirect("sso/login")
28
31
  get "logout", to: redirect("sso/logout")
29
32
  ```
30
33
 
31
- The engine now needs to be configured. First create a YAML config file, perhaps named `config/auth_sso.yml`, to configure your app's Auth0 settings. This assumes that the necessary Auth0 applications have been created in the correct Auth0 tenants. The [CPI auth_sso.yml file](https://github.com/nulogy/Common-Platform-Interface/blob/master/config/auth_sso.yml) is a good starting place.
34
+ The engine now needs to be configured. First create a YAML config file, perhaps named `config/auth_sso.yml`, to configure your app's Auth0 settings. This assumes that the necessary Auth0 applications have been created in the correct Auth0 tenants. An example configuration for local development would look like:
35
+
36
+ ```yaml
37
+ default: &default
38
+ audience: <%= ENV.fetch("SSO_AUDIENCE", "auth.nulogy.net") %>
39
+ client_id: <%= ENV.fetch("SSO_CLIENT_ID", "SSO CLIENT ID FROM AUTH0") %>
40
+ client_secret: <%= ENV.fetch("SSO_CLIENT_SECRET", "SSO CLIENT SECRET FROM AUTH0") %>
41
+ base_uri: <%= ENV.fetch("SSO_BASE_URI", "") %>
42
+ cookie_prefix: <%= ENV.fetch("SSO_COOKIE_PREFIX", "") %>
43
+ login_uri: <%= ENV.fetch("SSO_LOGIN_URI", "") %>
44
+ redirect_uri: <%= ENV.fetch("SSO_REDIRECT_URI", "") %>
45
+
46
+ development:
47
+ <<: *default
48
+ base_uri: <%= ENV.fetch("SSO_BASE_URI", "https://auth-dev.nulogy.net") %>
49
+ cookie_prefix: <%= ENV.fetch("SSO_COOKIE_PREFIX", "dev") %>
50
+ login_uri: <%= ENV.fetch("SSO_LOGIN_URI", "http://localhost:3000/sso/validate_authentication_code") %>
51
+ redirect_uri: <%= ENV.fetch("SSO_REDIRECT_URI", "http://localhost:3000") %>
52
+
53
+ test:
54
+ <<: *default
55
+
56
+ production:
57
+ <<: *default
58
+ ```
32
59
 
33
60
  With that available, you can configure the engine with an initializer file. This is where _NulogySSO_ can be customized according to your application's needs. Put the below code into `config/initializers/nulogy_sso.rb`, with the appropriate modifications implemented. For `sso_config`, refer to [nulogy_sso.rb](lib/nulogy_sso.rb) for a list of required keys and [sso_config.yml](spec/dummy/config/sso_config.yml) for an example config file.
34
61
 
@@ -43,7 +70,12 @@ NulogySSO.find_user_by_email = ->(email) { nil }
43
70
  # Handle errors from the SSO authentication flow, according to the app's design.
44
71
  # This includes internal errors from the Auth0 gem (ie, token signature mismatch) and no user from the app DB matching the email from the JWT.
45
72
  # The controller is passed as an argument to give the handler access to the "controller context", which is useful for tasks such as rendering a view.
46
- NulogySSO.handle_sso_error = ->(controller) { }
73
+ NulogySSO.handle_sso_error = ->(controller: , error:) { }
74
+
75
+ # Handle how unauthenticated requests should be responded to. The default is to redirect to the defined login page.
76
+ # For API based applications this should be overriden to provide a meaningful error as per your API's contract (i.e. an HTTP 401 error code)
77
+ # Additionally, this could be overriden if an application should bypass SSO when running tests.
78
+ NulogySSO.handle_unauthenticated_request = ->(controller) { controller.redirect_to sso_engine.login_path }
47
79
  ```
48
80
 
49
81
  The app is now ready to authenticate a user with Auth0! With NulogySSO and Auth0, the user's identity is maintained across requests (and apps!) via a [JWT](https://auth0.com/docs/jwt) stored as a browser cookie. Add this code to the `ApplicationController`:
@@ -16,32 +16,32 @@ module NulogySSO
16
16
  end
17
17
 
18
18
  def login
19
- raw_access_token = cookies[NulogySSO.sso_cookie_key]
19
+ raw_access_token = token_store.fetch
20
20
 
21
21
  authenticator.validate_token(
22
22
  raw_access_token,
23
23
  on_success: method(:on_authentication_success),
24
- on_invalid_token: -> { redirect_to auth0_authorize_path }
24
+ on_invalid_token: ->(_e) { redirect_to auth0_authorize_path }
25
25
  )
26
26
  end
27
27
 
28
- def code
28
+ def verify_authentication_code
29
29
  code = params.require(:code)
30
30
  begin
31
- raw_access_token = token_response(code)["access_token"]
31
+ raw_access_token = fetch_token_from_auth0(code)
32
32
  rescue Auth0::Exception => e
33
- return sso_error
33
+ return sso_error(e)
34
34
  end
35
35
 
36
36
  authenticator.validate_token(
37
37
  raw_access_token,
38
38
  on_success: method(:on_authentication_success),
39
- on_invalid_token: -> { sso_error }
39
+ on_invalid_token: ->(e) { sso_error(e) }
40
40
  )
41
41
  end
42
42
 
43
43
  def logout
44
- cookies.delete(NulogySSO.sso_cookie_key, domain: :all)
44
+ token_store.forget!
45
45
 
46
46
  query_params = {
47
47
  returnTo: sso_config.redirect_uri, # Yes, this must be camelCased
@@ -54,37 +54,32 @@ module NulogySSO
54
54
 
55
55
  delegate :sso_config, to: :NulogySSO
56
56
 
57
- def sso_error
58
- NulogySSO.handle_sso_error.call(self)
57
+ def sso_error(error)
58
+ NulogySSO.handle_sso_error.call(controller: self, error: error)
59
59
  end
60
60
 
61
61
  def authenticator
62
62
  @authenticator ||= Authenticator.new
63
63
  end
64
64
 
65
+ def token_store
66
+ @token_store ||= CookieTokenStore.new(request, response)
67
+ end
68
+
65
69
  def on_authentication_success(access_token)
66
- respond_with_cookies(access_token)
70
+ token_store.store!(access_token)
67
71
 
68
72
  redirect_to params["origin"].presence || sso_config.redirect_uri
69
73
  end
70
74
 
71
- def token_response(code)
72
- exchange_auth_code_for_tokens(
75
+ def fetch_token_from_auth0(code)
76
+ response = exchange_auth_code_for_tokens(
73
77
  code,
74
78
  redirect_uri: sso_config.login_uri,
75
79
  client_id: sso_config.client_id,
76
80
  client_secret: sso_config.client_secret
77
81
  )
78
- end
79
-
80
- def respond_with_cookies(access_token_value)
81
- cookies[NulogySSO.sso_cookie_key] = {
82
- value: access_token_value,
83
- domain: :all,
84
- expires: 36_000.seconds, # TODO: Fetch this value from the JWT
85
- httponly: true,
86
- secure: request.ssl?
87
- }
82
+ response["access_token"]
88
83
  end
89
84
 
90
85
  def auth0_authorize_path
@@ -10,6 +10,10 @@ module NulogySSO
10
10
  jwks_url: "#{NulogySSO.sso_config.base_uri}/.well-known/jwks.json"
11
11
  )
12
12
 
13
+ MissingUserError = Class.new(StandardError)
14
+ MissingTokenError = Class.new(StandardError)
15
+ InvalidTokenError = Class.new(StandardError)
16
+
13
17
  def initialize(verifier: ACCESS_TOKEN_VERIFIER, find_user_by_email: NulogySSO.find_user_by_email)
14
18
  @verifier = verifier
15
19
  @find_user_by_email = find_user_by_email
@@ -17,12 +21,13 @@ module NulogySSO
17
21
 
18
22
  # Validated the provided JWT, ensuring that an authenticated Auth0 user can be associated to the token and matches an existing app user
19
23
  def validate_token(raw_access_token, on_success:, on_invalid_token:)
20
- access_token = decoded_validated_access_token(raw_access_token)
24
+ return on_invalid_token.call(MissingTokenError.new) if raw_access_token.blank?
21
25
 
22
- return on_invalid_token.call if access_token.nil?
26
+ access_token = decoded_validated_access_token(raw_access_token)
27
+ return on_invalid_token.call(InvalidTokenError.new(raw_access_token)) if access_token.nil?
23
28
 
24
29
  user = fetch_user(access_token)
25
- return on_invalid_token.call if user.blank?
30
+ return on_invalid_token.call(MissingUserError.new(access_token)) if user.blank?
26
31
 
27
32
  on_success.call(access_token)
28
33
  end
@@ -0,0 +1,57 @@
1
+ module NulogySSO
2
+ # A class for storing the SSO token in cookies
3
+ #
4
+ # This uses the Rack level API instead of going through the Rails API because
5
+ # we have found that for our GraphQL based applications, using the cookiejar API
6
+ # has not been working. The cookies are not being set correctly, likely because
7
+ # the requests are resulting in 302 redirects.
8
+ class CookieTokenStore
9
+ def initialize(request, response)
10
+ @request = request
11
+ @response = response
12
+ end
13
+
14
+ def fetch
15
+ @request.cookie_jar[NulogySSO.sso_cookie_key]
16
+ end
17
+
18
+ def store!(access_token_value)
19
+ @response.set_cookie(
20
+ NulogySSO.sso_cookie_key,
21
+ value: access_token_value,
22
+ path: "/",
23
+ domain: all_domains,
24
+ expires: 36_000.seconds.from_now, # TODO: Fetch this value from the JWT
25
+ httponly: true,
26
+ secure: @request.ssl?
27
+ )
28
+ end
29
+
30
+ def forget!
31
+ @response.delete_cookie(
32
+ NulogySSO.sso_cookie_key,
33
+ path: "/",
34
+ domain: all_domains
35
+ )
36
+ end
37
+
38
+ private
39
+
40
+ DOMAIN_REGEXP = /[^.]*\.([^.]*|..\...|...\...)$/
41
+
42
+ ##
43
+ # This is copied from the Rails Cookie Helper at:
44
+ # https://github.com/rails/rails/blob/6-0-stable/actionpack/lib/action_dispatch/middleware/cookies.rb#L357
45
+ #
46
+ # This simulates the same { domain: :all } option which exists for interacting with the cookie jar
47
+ # even though not all clients will have access to the same cookie jar API (i.e. if you are building
48
+ # an API controller).
49
+ def all_domains
50
+ # If there is a provided tld length then we use it otherwise default domain regexp.
51
+ domain_regexp = DOMAIN_REGEXP
52
+ # If host is not ip and matches domain regexp.
53
+ # (ip confirms to domain regexp so we explicitly check for ip)
54
+ ".#{$&}" if (@request.host !~ /^[\d.]+$/) && (@request.host =~ domain_regexp)
55
+ end
56
+ end
57
+ end
data/config/routes.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  NulogySSO::Engine.routes.draw do
2
2
  get "login", to: "authentication#login"
3
3
  get "logout", to: "authentication#logout"
4
- get "code", to: "authentication#code"
4
+ get "verify_authentication_code", to: "authentication#verify_authentication_code"
5
5
  end
@@ -11,16 +11,16 @@ module NulogySSO
11
11
  # Makes the commonly used @current_user variable available to controllers and views.
12
12
  # This emulates a code pattern popular in Rails apps using Devise.
13
13
  attr_reader :current_user
14
- helper_method :current_user
14
+ helper_method :current_user if defined?(helper_method)
15
15
  before_action :store_previous_url_in_session
16
16
  end
17
17
 
18
18
  def authenticate_sso_user
19
- raw_token = cookies[NulogySSO.sso_cookie_key]
20
- return redirect_to nulogy_sso.login_path if raw_token.blank?
19
+ raw_token = CookieTokenStore.new(request, response).fetch
20
+ return NulogySSO.handle_unauthenticated_request.call(self) if raw_token.blank?
21
21
 
22
22
  @current_user = Authenticator.new.authenticated_user(raw_token)
23
- return redirect_to nulogy_sso.login_path if @current_user.blank?
23
+ return NulogySSO.handle_unauthenticated_request.call(self) if @current_user.blank?
24
24
  end
25
25
 
26
26
  def store_previous_url_in_session
@@ -40,7 +40,7 @@ module NulogySSO
40
40
  httpResponse: {
41
41
  statusCode: 302,
42
42
  headers: {
43
- Location: ["#{capybara_current_host}#{engine_path}/code?#{redirect_query_params}"]
43
+ Location: ["#{capybara_current_host}#{engine_path}/verify_authentication_code?#{redirect_query_params}"]
44
44
  }
45
45
  }
46
46
  )
@@ -1,3 +1,3 @@
1
1
  module NulogySSO
2
- VERSION = "1.0.0"
2
+ VERSION = "2.0.0"
3
3
  end
data/lib/nulogy_sso.rb CHANGED
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "nulogy_sso/engine"
4
- require "immutable-struct"
5
4
 
6
5
  module NulogySSO
7
6
  # Config variables for the engine
8
7
  mattr_accessor :sso_config, :find_user_by_email, :handle_sso_error
8
+ mattr_accessor :handle_unauthenticated_request, default: lambda { |controller|
9
+ controller.redirect_to NulogySSO::Engine.routes.url_helpers.login_path
10
+ }
9
11
 
10
12
  # Public Constants
11
13
  JWT_EMAIL_KEY = "https://nulogy.net/email"
@@ -32,7 +34,7 @@ module NulogySSO
32
34
  ]
33
35
  private_constant :REQUIRED_SSO_CONFIG_KEYS
34
36
 
35
- SSOConfig = ImmutableStruct.new(*REQUIRED_SSO_CONFIG_KEYS)
37
+ SSOConfig = Struct.new(*REQUIRED_SSO_CONFIG_KEYS, keyword_init: true)
36
38
 
37
39
  def self.sso_cookie_key
38
40
  "#{sso_config.cookie_prefix}_access_token"
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This controller is essential for running Capybara feature tests against the NulogySSO engine
4
+ class ApiController < ActionController::API
5
+ include NulogySSO::ControllerHelper
6
+
7
+ before_action :authenticate_sso_user
8
+
9
+ def api_endpoint
10
+ render json: {text: "Hello World"}
11
+ end
12
+ end
@@ -35,7 +35,7 @@ module Dummy
35
35
  # These functions are mostly used for testing.
36
36
  NulogySSO.sso_config = config_for(:sso)
37
37
  NulogySSO.find_user_by_email = ->(email) { User.find_by(email: email) }
38
- NulogySSO.handle_sso_error = ->(controller) { controller.render plain: "An SSO error has occurred :(" }
38
+ NulogySSO.handle_sso_error = ->(controller:, **) { controller.render plain: "An SSO error has occurred :(" }
39
39
  end
40
40
  end
41
41
 
@@ -3,4 +3,5 @@ Rails.application.routes.draw do
3
3
 
4
4
  # Essential for Capybara feature tests
5
5
  get "/hello_world", to: "application#hello_world"
6
+ get "/api_endpoint", to: "api#api_endpoint"
6
7
  end
@@ -74,6 +74,44 @@ module NulogySSO
74
74
  end
75
75
  end
76
76
 
77
+ describe "authenticated APIs" do
78
+ let!(:user) { create_user }
79
+
80
+ before do
81
+ auth0_mock.mockserver_reset
82
+ auth0_mock.setup_jwks
83
+
84
+ # have to visit an unauthenticated endpoint in order for capybara to have something to have a tab to set the cookie on
85
+ visit "/robots.txt"
86
+ end
87
+
88
+ it "allows a user with a valid JWT to visit a secured endpoint" do
89
+ set_access_token_cookie(jwt_test_helper.jwt(email))
90
+
91
+ visit "/api_endpoint"
92
+
93
+ expect(page).to have_content("Hello World")
94
+ end
95
+
96
+ it "prevents sessions with invalid JWTs from accessing secured endpoints" do
97
+ set_access_token_cookie(jwt_test_helper.jwt(email, "exp" => (Time.now - 1.day).to_i))
98
+
99
+ visit "/api_endpoint"
100
+
101
+ expect(current_path).to eq("/authorize")
102
+ end
103
+
104
+ it "prevents sessions with no JWT from accessing secured endpoints" do
105
+ visit "/api_endpoint"
106
+
107
+ expect(current_path).to eq("/authorize")
108
+ end
109
+
110
+ def set_access_token_cookie(token)
111
+ page.driver.browser.manage.add_cookie(name: NulogySSO.sso_cookie_key, value: token)
112
+ end
113
+ end
114
+
77
115
  def create_user
78
116
  User.create!(email: email)
79
117
  end
@@ -25,7 +25,7 @@ module NulogySSO
25
25
  it "calls on_invalid_token when the access token is blank" do
26
26
  [nil, "", false].each(&method(:validate_token))
27
27
 
28
- expect(on_invalid_token).to have_received(:call).exactly(3).times
28
+ expect(on_invalid_token).to have_received(:call).exactly(3).times.with(NulogySSO::Authenticator::MissingTokenError)
29
29
  end
30
30
 
31
31
  context "JWT passes verification" do
@@ -43,7 +43,7 @@ module NulogySSO
43
43
 
44
44
  validate_token(valid_signed_token, authenticator: authenticator)
45
45
 
46
- expect(on_invalid_token).to have_received(:call).once
46
+ expect(on_invalid_token).to have_received(:call).once.with(NulogySSO::Authenticator::MissingUserError)
47
47
  end
48
48
  end
49
49
 
@@ -51,7 +51,7 @@ module NulogySSO
51
51
  it "calls the invalid token handler" do
52
52
  validate_token(invalid_signed_token)
53
53
 
54
- expect(on_invalid_token).to have_received(:call).once
54
+ expect(on_invalid_token).to have_received(:call).once.with(NulogySSO::Authenticator::InvalidTokenError)
55
55
  end
56
56
  end
57
57
 
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NulogySSO
4
+ RSpec.describe CookieTokenStore do
5
+ let(:request) { double(host: "some_app.nulogy.net", ssl?: false) }
6
+ let(:response) { double(set_cookie: spy, delete_cookie: spy) }
7
+
8
+ subject(:token_store) { CookieTokenStore.new(request, response) }
9
+
10
+ before do
11
+ freeze_time
12
+ end
13
+
14
+ it "extracts the top level domain from a domain name" do
15
+ allow(request).to receive(:host).and_return("some.app.nulogy.net")
16
+ token_store.store!("anything")
17
+ expect(response).to have_received(:set_cookie).with(anything, hash_including(domain: ".nulogy.net"))
18
+ end
19
+
20
+ it "stores the cookie value with the correct settings" do
21
+ token_store.store!("cookie value")
22
+
23
+ expect(response).to have_received(:set_cookie).with(
24
+ "mock_cookie_prefix_access_token",
25
+ value: "cookie value",
26
+ path: "/",
27
+ domain: ".nulogy.net",
28
+ expires: 36_000.seconds.from_now,
29
+ httponly: true,
30
+ secure: false
31
+ )
32
+ end
33
+
34
+ it "deletes the cookie matching the path, domain and key" do
35
+ token_store.forget!
36
+
37
+ expect(response).to have_received(:delete_cookie).with(
38
+ "mock_cookie_prefix_access_token",
39
+ path: "/",
40
+ domain: ".nulogy.net",
41
+ )
42
+ end
43
+ end
44
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ require 'active_support/testing/time_helpers'
2
3
 
3
4
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
4
5
  RSpec.configure do |config|
@@ -40,4 +41,6 @@ RSpec.configure do |config|
40
41
 
41
42
  # Seed global randomization in this process using the `--seed` CLI option.
42
43
  Kernel.srand config.seed
44
+
45
+ config.include ActiveSupport::Testing::TimeHelpers
43
46
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nulogy_sso
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nulogy Corporation
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-09-30 00:00:00.000000000 Z
11
+ date: 2019-10-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: auth0
@@ -38,20 +38,6 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.0.2
41
- - !ruby/object:Gem::Dependency
42
- name: immutable-struct
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '2.4'
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '2.4'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: rails
57
43
  requirement: !ruby/object:Gem::Requirement
@@ -167,6 +153,7 @@ files:
167
153
  - Rakefile
168
154
  - app/controllers/nulogy_sso/authentication_controller.rb
169
155
  - app/services/nulogy_sso/authenticator.rb
156
+ - app/services/nulogy_sso/cookie_token_store.rb
170
157
  - config/initializers/inflections.rb
171
158
  - config/routes.rb
172
159
  - lib/nulogy_sso.rb
@@ -183,6 +170,7 @@ files:
183
170
  - spec/dummy/app/assets/stylesheets/application.css
184
171
  - spec/dummy/app/channels/application_cable/channel.rb
185
172
  - spec/dummy/app/channels/application_cable/connection.rb
173
+ - spec/dummy/app/controllers/api_controller.rb
186
174
  - spec/dummy/app/controllers/application_controller.rb
187
175
  - spec/dummy/app/helpers/application_helper.rb
188
176
  - spec/dummy/app/jobs/application_job.rb
@@ -327,6 +315,7 @@ files:
327
315
  - spec/feature_spec_helper.rb
328
316
  - spec/features/nulogy_sso/sso_login_spec.rb
329
317
  - spec/integration/services/nulogy_sso/authenticator_spec.rb
318
+ - spec/integration/services/nulogy_sso/cookie_token_store_spec.rb
330
319
  - spec/rails_helper.rb
331
320
  - spec/spec_helper.rb
332
321
  - spec/support/mock_auth0_verifier.rb
@@ -341,7 +330,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
341
330
  requirements:
342
331
  - - ">="
343
332
  - !ruby/object:Gem::Version
344
- version: '0'
333
+ version: '2.5'
345
334
  required_rubygems_version: !ruby/object:Gem::Requirement
346
335
  requirements:
347
336
  - - ">="
@@ -358,6 +347,7 @@ test_files:
358
347
  - spec/dummy/app/models/user.rb
359
348
  - spec/dummy/app/jobs/application_job.rb
360
349
  - spec/dummy/app/controllers/application_controller.rb
350
+ - spec/dummy/app/controllers/api_controller.rb
361
351
  - spec/dummy/app/views/layouts/application.html.erb
362
352
  - spec/dummy/app/assets/config/manifest.js
363
353
  - spec/dummy/app/assets/javascripts/application.js
@@ -502,6 +492,7 @@ test_files:
502
492
  - spec/dummy/tmp/cache/assets/sprockets/v3.0/qj/qjq5Ug3S2i5pydfGSIfUa7Y0s8s0FwqXzt0kkFijToI.cache
503
493
  - spec/examples.txt
504
494
  - spec/integration/services/nulogy_sso/authenticator_spec.rb
495
+ - spec/integration/services/nulogy_sso/cookie_token_store_spec.rb
505
496
  - spec/features/nulogy_sso/sso_login_spec.rb
506
497
  - spec/support/mock_auth0_verifier.rb
507
498
  - spec/feature_spec_helper.rb