zaikio-oauth_client 0.8.1 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 32791412d8324e894c609e9ba73c1bc2fabb756117b91d81012d208730dfd5c2
4
- data.tar.gz: a1af7430748c3bce9e0d8058de85edcbdf0e2ecc3b568b389184e13b8945753d
3
+ metadata.gz: 2e007c62cd36b1b00aa8e542958bb5d627b5ca417ffc6559f45de3868e79149a
4
+ data.tar.gz: 9977c82c5f734d93b05269a7e9fb30e6fe6df1b15a291d680a48fa38bea079a8
5
5
  SHA512:
6
- metadata.gz: 6a33fdbb048a31fb157b006606ecbebbe69ac7950e17a25e1c3817f02485b15d8e7726c10fc8277ca57b6ea0a4781264d3055f188a0883613b053605e9a990a6
7
- data.tar.gz: 6e404b985ce76339e9edf1612b2db4d0d686c9b75f67ae8f4ff131c80e806a5911a223681d2abbbbbf03b72c3e155c66a891e45a696da403cdac095c2b1513f2
6
+ metadata.gz: eeb3f43dc40d4cabeb1f585864ff76c716243e6d0336164b0e3b98c7e2e41bdbd25ffdeaeeeb4b7ee1ccefe20cf1f458bd0af62e1cb2238af3ad258ad6cf4804
7
+ data.tar.gz: e3b47a58b780c92ed0b8a9c5ae0df7011026feed340204e8deb80a88ca2562b4a220cd59c8d5907982488001b6738d5c0eb0ba2495771c0de2a0310f44de42bd
data/README.md CHANGED
@@ -118,14 +118,27 @@ redirect_to zaikio_oauth_client.new_session_path(force_login: true)
118
118
  redirect_to zaikio_oauth_client.new_session_path(state: "something-my-app-uses")
119
119
  ```
120
120
 
121
+ You can also send them to the [Subscription Redirect
122
+ flow](https://docs.zaikio.com/api/directory/guides/subscriptions/redirect-flow/), which
123
+ behaves & redirects back like a regular Organization flow except it additionally sets up a
124
+ subscription for the organization:
125
+
126
+ ```ruby
127
+ # Require them to select a plan themselves...
128
+ redirect_to zaikio_oauth_client.new_subscription_path
129
+
130
+ # Or preselect a plan for them
131
+ redirect_to zaikio_oauth_client.new_subscription_path(plan: "free")
132
+ ```
133
+
121
134
  #### Session handling
122
135
 
123
- The Zaikio gem engine will set a cookie for the user after a successful OAuth flow: `cookies.encrypted[:zaikio_person_id]`.
136
+ The Zaikio gem engine will set a cookie for the user after a successful OAuth flow: `session[:zaikio_person_id]`.
124
137
 
125
138
  If you are using for example `Zaikio::Hub::Models`, you can use this snippet to set the current user:
126
139
 
127
140
  ```ruby
128
- Current.user ||= Zaikio::Hub::Models::Person.find_by(id: cookies.encrypted[:zaikio_person_id])
141
+ Current.user ||= Zaikio::Hub::Models::Person.find_by(id: session[:zaikio_person_id])
129
142
  ````
130
143
 
131
144
  You can then use `Current.user` anywhere.
@@ -159,7 +172,7 @@ Additionally you can also specify your own redirect handlers in your `Applicatio
159
172
  ```rb
160
173
  class ApplicationController < ActionController::Base
161
174
  def after_approve_path_for(access_token, origin)
162
- cookies.encrypted[:zaikio_person_id] = access_token.bearer_id unless access_token.organization?
175
+ session[:zaikio_person_id] = access_token.bearer_id unless access_token.organization?
163
176
 
164
177
  # Sync data on login
165
178
  Zaikio::Hub.with_token(access_token.token) do
@@ -170,8 +183,13 @@ class ApplicationController < ActionController::Base
170
183
  end
171
184
 
172
185
  def after_destroy_path_for(access_token_id)
173
- cookies.delete :zaikio_person_id
186
+ reset_session
187
+
188
+ main_app.root_path
189
+ end
174
190
 
191
+ def error_path_for(error_code, description: nil)
192
+ # Handle error
175
193
  main_app.root_path
176
194
  end
177
195
  end
@@ -254,7 +272,7 @@ To release a new version of the gem:
254
272
  - Update the version in `lib/zaikio/oauth_client/version.rb`
255
273
  - Update `CHANGELOG.md` to include the new version and its release date
256
274
  - Commit and push your changes
257
- - Create a [new release on GitHub](https://github.com/zaikio/zaikio-directory-models/releases/new)
275
+ - Create a [new release on GitHub](https://github.com/zaikio/zaikio-oauth_client/releases/new)
258
276
  - CircleCI will build the Gem package and push it Rubygems for you
259
277
 
260
278
  ## License
@@ -0,0 +1,28 @@
1
+ module Zaikio
2
+ module OAuthClient
3
+ class SubscriptionsController < ConnectionsController
4
+ def new
5
+ opts = params.permit(:client_name, :state, :plan, :organization_id)
6
+ opts[:redirect_with_error] = 1
7
+ opts[:state] ||= session[:state] = SecureRandom.urlsafe_base64(32)
8
+
9
+ plan = opts.delete(:plan)
10
+ organization_id = opts.delete(:organization_id)
11
+
12
+ subscription_scope = if organization_id.present?
13
+ "Org/#{organization_id}.subscription_create"
14
+ else
15
+ "Org.subscription_create"
16
+ end
17
+
18
+ subscription_scope << ".#{plan}" if plan.present?
19
+
20
+ redirect_to oauth_client.auth_code.authorize_url(
21
+ redirect_uri: approve_url(opts.delete(:client_name)),
22
+ scope: subscription_scope,
23
+ **opts
24
+ )
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,4 @@
1
+ de:
2
+ zaikio:
3
+ oauth_client:
4
+ error_occured: "Beim Login ist ein Fehler aufgetreten: %{error} %{description}. Bitte versuche es nochmal."
@@ -1,6 +1,7 @@
1
1
  en:
2
2
  zaikio:
3
+ oauth_client:
4
+ error_occured: "An error occurred during login: %{error} %{description}. Please try again."
3
5
  forms:
4
6
  optional: Optional
5
7
  learn_more: Learn more
6
-
data/config/routes.rb CHANGED
@@ -1,15 +1,17 @@
1
1
  Zaikio::OAuthClient::Engine.routes.draw do
2
- sessions_controller = Zaikio::OAuthClient.configuration.sessions_controller_name
3
- connections_controller = Zaikio::OAuthClient.configuration.connections_controller_name
2
+ config = Zaikio::OAuthClient.configuration
4
3
 
5
- # People
6
- get "(/:client_name)/sessions/new", action: :new, controller: sessions_controller, as: :new_session
7
- get "(/:client_name)/sessions/approve", action: :approve, controller: sessions_controller, as: :approve_session
8
- delete "(/:client_name)/session", action: :destroy, controller: sessions_controller, as: :session
4
+ scope path: "(/:client_name)" do
5
+ # People
6
+ get "/sessions/new", action: :new, controller: config.sessions_controller_name, as: :new_session
7
+ get "/sessions/approve", action: :approve, controller: config.sessions_controller_name, as: :approve_session
8
+ delete "/session", action: :destroy, controller: config.sessions_controller_name, as: :session
9
9
 
10
- # Organizations
11
- get "(/:client_name)/connections/new", action: :new,
12
- controller: connections_controller, as: :new_connection
13
- get "(/:client_name)/connections/approve", action: :approve,
14
- controller: connections_controller, as: :approve_connection
10
+ # Organizations
11
+ get "/connections/new", action: :new, controller: config.connections_controller_name, as: :new_connection
12
+ get "/connections/approve", action: :approve, controller: config.connections_controller_name, as: :approve_connection
13
+
14
+ # Subscriptions
15
+ get "/subscriptions/new", action: :new, controller: config.subscriptions_controller_name, as: :new_subscription
16
+ end
15
17
  end
@@ -1,5 +1,6 @@
1
1
  require "oauth2"
2
2
 
3
+ require "zaikio/oauth_client/error"
3
4
  require "zaikio/oauth_client/engine"
4
5
  require "zaikio/oauth_client/configuration"
5
6
  require "zaikio/oauth_client/authenticatable"
@@ -82,14 +83,25 @@ module Zaikio
82
83
  # Finds the best usable access token. Note that this token may have expired and
83
84
  # would require refreshing.
84
85
  def find_usable_access_token(client_name:, bearer_type:, bearer_id:, requested_scopes:)
85
- Zaikio::AccessToken
86
- .where(audience: client_name)
87
- .usable(
88
- bearer_type: bearer_type,
89
- bearer_id: bearer_id,
90
- requested_scopes: requested_scopes
91
- )
92
- .first
86
+ configuration.logger.debug "Try to fetch token for client_name: #{client_name}, "\
87
+ "bearer #{bearer_type}/#{bearer_id}, requested_scopes: #{requested_scopes}"
88
+
89
+ fetch_access_token = lambda {
90
+ Zaikio::AccessToken
91
+ .where(audience: client_name)
92
+ .usable(
93
+ bearer_type: bearer_type,
94
+ bearer_id: bearer_id,
95
+ requested_scopes: requested_scopes
96
+ )
97
+ .first
98
+ }
99
+
100
+ if configuration.logger.respond_to?(:silence)
101
+ configuration.logger.silence { fetch_access_token.call }
102
+ else
103
+ fetch_access_token.call
104
+ end
93
105
  end
94
106
 
95
107
  def fetch_new_token(client_config:, bearer_type:, bearer_id:, scopes:)
@@ -5,7 +5,9 @@ module Zaikio
5
5
 
6
6
  def new
7
7
  opts = params.permit(:client_name, :show_signup, :force_login, :state)
8
+ opts[:redirect_with_error] = 1
8
9
  client_name = opts.delete(:client_name)
10
+ opts[:state] ||= session[:state] = SecureRandom.urlsafe_base64(32)
9
11
 
10
12
  redirect_to oauth_client.auth_code.authorize_url(
11
13
  redirect_uri: approve_url(client_name),
@@ -15,12 +17,27 @@ module Zaikio
15
17
  end
16
18
 
17
19
  def approve
20
+ if params[:error].present?
21
+ redirect_to send(
22
+ respond_to?(:error_path_for) ? :error_path_for : :default_error_path_for,
23
+ params[:error],
24
+ description: params[:error_description]
25
+ ) and return
26
+ end
27
+
28
+ if session[:state].present? && params[:state] != session[:state]
29
+ return redirect_to send(
30
+ respond_to?(:error_path_for) ? :error_path_for : :default_error_path_for,
31
+ "invalid_state"
32
+ )
33
+ end
34
+
18
35
  access_token = create_access_token
19
36
 
20
- origin = cookies.encrypted[:origin]
21
- cookies.delete :origin
37
+ origin = session[:origin]
38
+ session.delete(:origin)
22
39
 
23
- cookies.encrypted[:zaikio_access_token_id] = access_token.id unless access_token.organization?
40
+ session[:zaikio_access_token_id] = access_token.id unless access_token.organization?
24
41
 
25
42
  redirect_to send(
26
43
  respond_to?(:after_approve_path_for) ? :after_approve_path_for : :default_after_approve_path_for,
@@ -29,8 +46,9 @@ module Zaikio
29
46
  end
30
47
 
31
48
  def destroy
32
- access_token_id = cookies.encrypted[:zaikio_access_token_id]
33
- cookies.delete :zaikio_access_token_id
49
+ access_token_id = session[:zaikio_access_token_id]
50
+ session.delete(:zaikio_access_token_id)
51
+ session.delete(:origin)
34
52
 
35
53
  redirect_to send(
36
54
  respond_to?(:after_destroy_path_for) ? :after_destroy_path_for : :default_after_destroy_path_for,
@@ -77,13 +95,23 @@ module Zaikio
77
95
  end
78
96
 
79
97
  def default_after_approve_path_for(access_token, origin)
80
- cookies.encrypted[:zaikio_person_id] = access_token.bearer_id unless access_token.organization?
98
+ session[:zaikio_person_id] = access_token.bearer_id unless access_token.organization?
81
99
 
82
100
  origin || main_app.root_path
83
101
  end
84
102
 
85
103
  def default_after_destroy_path_for(_access_token_id)
86
- cookies.delete :zaikio_person_id
104
+ session.delete(:origin)
105
+
106
+ main_app.root_path
107
+ end
108
+
109
+ def default_error_path_for(error_code, description: nil)
110
+ raise Zaikio::OAuthClient::InvalidScopesError, description if error_code == "invalid_scope"
111
+
112
+ unless error_code == "access_denied"
113
+ flash[:alert] = I18n.t("zaikio.oauth_client.error_occured", error: error_code, description: description)
114
+ end
87
115
 
88
116
  main_app.root_path
89
117
  end
@@ -13,19 +13,25 @@ module Zaikio
13
13
  }.freeze
14
14
 
15
15
  attr_accessor :host
16
- attr_writer :logger
17
16
  attr_reader :client_configurations, :environment, :around_auth_block,
18
- :sessions_controller_name, :connections_controller_name
17
+ :sessions_controller_name, :connections_controller_name, :subscriptions_controller_name
19
18
 
20
19
  def initialize
21
20
  @client_configurations = {}
22
21
  @around_auth_block = nil
23
22
  @sessions_controller_name = "sessions"
24
23
  @connections_controller_name = "connections"
24
+ @subscriptions_controller_name = "subscriptions"
25
+ Zaikio::AccessToken.logger = logger
25
26
  end
26
27
 
27
28
  def logger
28
- @logger ||= Logger.new($stdout)
29
+ @logger ||= ActiveSupport::Logger.new($stdout)
30
+ end
31
+
32
+ def logger=(logger)
33
+ @logger = logger
34
+ Zaikio::AccessToken.logger = @logger
29
35
  end
30
36
 
31
37
  def register_client(name)
@@ -58,6 +64,10 @@ module Zaikio
58
64
  @connections_controller_name = "/#{name}"
59
65
  end
60
66
 
67
+ def subscriptions_controller_name=(name)
68
+ @subscriptions_controller_name = "/#{name}"
69
+ end
70
+
61
71
  private
62
72
 
63
73
  def host_for(environment)
@@ -0,0 +1,5 @@
1
+ module Zaikio
2
+ module OAuthClient
3
+ class InvalidScopesError < StandardError; end
4
+ end
5
+ end
@@ -3,13 +3,48 @@ module Zaikio
3
3
  module TestHelper
4
4
  extend ActiveSupport::Concern
5
5
 
6
- def logged_in_as(person)
7
- # We need to manually encrypt the value since the tests cookie jar does not
8
- # support encrypted or signed cookies
9
- encrypted_cookies = ActionDispatch::Request.new(Rails.application.env_config.deep_dup).cookie_jar
10
- encrypted_cookies.encrypted[:zaikio_person_id] = person.id
6
+ class TestSessionController < ActionController::Base
7
+ def show
8
+ if session[params[:key]].nil?
9
+ head :no_content
10
+ else
11
+ render plain: session[params[:key]]
12
+ end
13
+ end
14
+
15
+ def create
16
+ session[params[:key]] = params[:id]
17
+
18
+ head :ok
19
+ end
20
+ end
21
+
22
+ included do
23
+ # This is needed as it is not possible to set sesison values in an ActionDispatch::IntegrationTest
24
+ # This creates a dummy controller to set the session
25
+ Rails.application.routes.disable_clear_and_finalize = true # Keep existing routes
26
+ Rails.application.routes.draw do
27
+ get "/zaikio/oauth_client/test_helper/get_session", to: "zaikio/oauth_client/test_helper/test_session#show"
28
+ get "/zaikio/oauth_client/test_helper/session", to: "zaikio/oauth_client/test_helper/test_session#create"
29
+ end
30
+ end
11
31
 
12
- cookies["zaikio_person_id"] = encrypted_cookies["zaikio_person_id"]
32
+ def get_session(key)
33
+ get "/zaikio/oauth_client/test_helper/get_session", params: { key: key }
34
+
35
+ if response.status == 204
36
+ nil
37
+ else
38
+ response.body
39
+ end
40
+ end
41
+
42
+ def set_session(key, value)
43
+ get "/zaikio/oauth_client/test_helper/session", params: { id: value, key: key }
44
+ end
45
+
46
+ def logged_in_as(person)
47
+ set_session(:zaikio_person_id, person.id)
13
48
  end
14
49
  end
15
50
  end
@@ -1,5 +1,5 @@
1
1
  module Zaikio
2
2
  module OAuthClient
3
- VERSION = "0.8.1".freeze
3
+ VERSION = "0.12.0".freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zaikio-oauth_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zaikio GmbH
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-31 00:00:00.000000000 Z
11
+ date: 2021-04-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -84,22 +84,16 @@ dependencies:
84
84
  name: zaikio-jwt_auth
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: 0.2.1
90
- - - "<"
87
+ - - "~>"
91
88
  - !ruby/object:Gem::Version
92
- version: 0.5.0
89
+ version: '0.5'
93
90
  type: :runtime
94
91
  prerelease: false
95
92
  version_requirements: !ruby/object:Gem::Requirement
96
93
  requirements:
97
- - - ">="
98
- - !ruby/object:Gem::Version
99
- version: 0.2.1
100
- - - "<"
94
+ - - "~>"
101
95
  - !ruby/object:Gem::Version
102
- version: 0.5.0
96
+ version: '0.5'
103
97
  - !ruby/object:Gem::Dependency
104
98
  name: pg
105
99
  requirement: !ruby/object:Gem::Requirement
@@ -144,11 +138,13 @@ files:
144
138
  - Rakefile
145
139
  - app/controllers/zaikio/oauth_client/connections_controller.rb
146
140
  - app/controllers/zaikio/oauth_client/sessions_controller.rb
141
+ - app/controllers/zaikio/oauth_client/subscriptions_controller.rb
147
142
  - app/helpers/zaikio/application_helper.rb
148
143
  - app/jobs/zaikio/application_job.rb
149
144
  - app/jobs/zaikio/cleanup_access_tokens_job.rb
150
145
  - app/models/zaikio/access_token.rb
151
146
  - config/initializers/inflections.rb
147
+ - config/locales/de.yml
152
148
  - config/locales/en.yml
153
149
  - config/routes.rb
154
150
  - db/migrate/20190426155505_enable_postgres_extensions_for_uuids.rb
@@ -161,13 +157,14 @@ files:
161
157
  - lib/zaikio/oauth_client/client_configuration.rb
162
158
  - lib/zaikio/oauth_client/configuration.rb
163
159
  - lib/zaikio/oauth_client/engine.rb
160
+ - lib/zaikio/oauth_client/error.rb
164
161
  - lib/zaikio/oauth_client/test_helper.rb
165
162
  - lib/zaikio/oauth_client/version.rb
166
163
  homepage: https://github.com/zaikio/zaikio-oauth_client
167
164
  licenses:
168
165
  - MIT
169
166
  metadata:
170
- changelog_uri: https://github.com/zaikio/zaikio-oauth_client/blob/master/CHANGELOG.md
167
+ changelog_uri: https://github.com/zaikio/zaikio-oauth_client/blob/main/CHANGELOG.md
171
168
  post_install_message:
172
169
  rdoc_options: []
173
170
  require_paths: