standard_id 0.2.1 → 0.2.3

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: acbf22ea3a73945fedbcc5d26da84954f4b4e04de00cf2bac51eb59374231a09
4
- data.tar.gz: 063d9c263aa7ca6910602a1a570676ee96348a88b1265a2c2ac5d8c11dacf076
3
+ metadata.gz: b187dd81d274ace6321becb8a2be32bf28968ab27d845d698294ff2ec448ad53
4
+ data.tar.gz: 3deb68b18b7d5ad8a4075c303ebe03cf93fc0fd0a74b1ef399736688e62f35ab
5
5
  SHA512:
6
- metadata.gz: 8a3e58978c5525de51c16ad46e563567a93790a7ad5a99aeea1d43d3068c01df9120ccc5d0a5694a5e3531fe916906bcc811f2a2dcbce25ec42228ca7ddfa4e5
7
- data.tar.gz: 2f3d4beee53b0fa961ed8648eb433a65e751f63c8f20fa10153e10c16bfce50440a5714bbd9b8a8cc4fefe98ff806804c6f49e6e3a79362b10e9780a55d49fce
6
+ metadata.gz: 1e64c713cd3861aba0ceb1f946d881effc025439807eb30e7ea373052c9890e077a654257e940e6379c7ae743a90fa8736ece2139bb92dd2b9a284b943c48ed2
7
+ data.tar.gz: c61fd9e8033cbbd91903e31933b3d1f0c77b34298a672e77b77af0478b3a64eec011674a1c21b3db5111f60277baf3a71357cd021c45eb2e1dba7222fe828e62
data/README.md CHANGED
@@ -101,6 +101,26 @@ class ApiController < ActionController::API
101
101
  end
102
102
  ```
103
103
 
104
+ ### 5. Action Cable Authentication
105
+
106
+ - Include in Your Connection Class
107
+ ```ruby
108
+ module ApplicationCable
109
+ class Connection < ActionCable::Connection::Base
110
+ include StandardId::CableAuthentication
111
+ end
112
+ end
113
+ ```
114
+
115
+ - Access Current Account in Channels
116
+ ```ruby
117
+ class ChatChannel < ApplicationCable::Channel
118
+ def subscribed
119
+ stream_for current_account
120
+ end
121
+ end
122
+ ```
123
+
104
124
  ## Configuration
105
125
 
106
126
  ### Basic Configuration
@@ -0,0 +1,33 @@
1
+ module StandardId
2
+ module CableAuthentication
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ identified_by :current_account
7
+ end
8
+
9
+ def connect
10
+ self.current_account = find_verified_account
11
+ end
12
+
13
+ private
14
+
15
+ def find_verified_account
16
+ if verified_account = find_account_from_session_token
17
+ verified_account
18
+ else
19
+ reject_unauthorized_connection
20
+ end
21
+ end
22
+
23
+ def find_account_from_session_token
24
+ session_token = cookies.encrypted[:session_token] || request.session[:session_token]
25
+ return nil if session_token.blank?
26
+
27
+ browser_session = StandardId::BrowserSession.eager_load(:account).by_token(session_token).first
28
+ return nil unless browser_session&.active?
29
+
30
+ browser_session.account
31
+ end
32
+ end
33
+ end
@@ -16,7 +16,8 @@ module StandardId
16
16
  params,
17
17
  request,
18
18
  account:,
19
- connection: provider.provider_name
19
+ connection: provider.provider_name,
20
+ scopes: params[:scope] || params[:scopes]
20
21
  )
21
22
 
22
23
  token_response = flow.execute
@@ -24,7 +25,7 @@ module StandardId
24
25
  provider: provider.provider_name,
25
26
  social_info:,
26
27
  provider_tokens:,
27
- account:
28
+ account:,
28
29
  )
29
30
  render json: token_response, status: :ok
30
31
  end
@@ -60,6 +60,7 @@ StandardId.configure do |c|
60
60
  # c.social.apple_key_id = ENV["APPLE_KEY_ID"]
61
61
  # c.social.apple_team_id = ENV["APPLE_TEAM_ID"]
62
62
  # c.social.allowed_redirect_url_prefixes = ["sidekicklabs://"]
63
+ # c.social.available_scopes = ["profile", "email", "offline_access"]
63
64
  # c.social.social_account_attributes = ->(social_info:, provider:) {
64
65
  # {
65
66
  # email: social_info[:email],
@@ -55,5 +55,6 @@ StandardConfig.schema.draw do
55
55
  scope :social do
56
56
  field :social_account_attributes, type: :any, default: nil
57
57
  field :allowed_redirect_url_prefixes, type: :array, default: []
58
+ field :available_scopes, type: :array, default: -> { [] }
58
59
  end
59
60
  end
@@ -1,12 +1,13 @@
1
1
  module StandardId
2
2
  module Oauth
3
3
  class SocialFlow < TokenGrantFlow
4
- attr_reader :account, :connection, :original_params
4
+ attr_reader :account, :connection, :scopes
5
5
 
6
- def initialize(params, request, account:, connection:)
6
+ def initialize(params, request, account:, connection:, scopes:)
7
7
  super(params, request)
8
8
  @account = account
9
9
  @connection = connection
10
+ @scopes = validate_and_normalize_scopes(scopes)
10
11
  end
11
12
 
12
13
  def authenticate!
@@ -24,7 +25,7 @@ module StandardId
24
25
  end
25
26
 
26
27
  def token_scope
27
- nil
28
+ scopes
28
29
  end
29
30
 
30
31
  def grant_type
@@ -51,6 +52,22 @@ module StandardId
51
52
  base_payload = super(expires_in)
52
53
  base_payload.merge(provider: @connection).compact
53
54
  end
55
+
56
+ def validate_and_normalize_scopes(scopes)
57
+ return nil if scopes.blank?
58
+
59
+ available_scopes = StandardId.config.social.available_scopes
60
+ return scopes if available_scopes.blank?
61
+
62
+ requested_scopes = scopes.to_s.split(/\s+/).reject(&:blank?).uniq
63
+ invalid_scopes = requested_scopes - available_scopes.map(&:to_s)
64
+
65
+ if invalid_scopes.any?
66
+ raise StandardId::InvalidScopeError, "Invalid scope(s): #{invalid_scopes.join(', ')}. Available scopes: #{available_scopes.join(', ')}"
67
+ end
68
+
69
+ requested_scopes.join(" ")
70
+ end
54
71
  end
55
72
  end
56
73
  end
@@ -1,3 +1,3 @@
1
1
  module StandardId
2
- VERSION = "0.2.1"
2
+ VERSION = "0.2.3"
3
3
  end
@@ -21,7 +21,10 @@ module StandardId
21
21
  def sign_in_account(account)
22
22
  emit_session_creating(account, "browser")
23
23
  token_manager.create_browser_session(account).tap do |browser_session|
24
+ # Store in both session and encrypted cookie for backward compatibility
25
+ # Action Cable will use the encrypted cookie
24
26
  session[:session_token] = browser_session.token
27
+ cookies.encrypted[:session_token] = browser_session.token
25
28
  Current.session = browser_session
26
29
  emit_session_created(browser_session, account, "browser")
27
30
  end
@@ -39,6 +42,7 @@ module StandardId
39
42
  def clear_session!
40
43
  # TODO: make token key names configurable
41
44
  session.delete(:session_token)
45
+ cookies.encrypted[:session_token] = nil
42
46
  cookies.delete(:remember_token)
43
47
 
44
48
  Current.session = nil
@@ -65,7 +69,9 @@ module StandardId
65
69
  end
66
70
 
67
71
  def load_session_from_session_token
68
- StandardId::BrowserSession.eager_load(:account).by_token(session[:session_token]).first
72
+ # Try encrypted cookie first (for Action Cable), then fall back to session (for backward compatibility)
73
+ session_token = cookies.encrypted[:session_token] || session[:session_token]
74
+ StandardId::BrowserSession.eager_load(:account).by_token(session_token).first
69
75
  end
70
76
 
71
77
  def load_session_from_remember_token
@@ -73,7 +79,9 @@ module StandardId
73
79
  return if password_credential.blank?
74
80
 
75
81
  token_manager.create_browser_session(password_credential.account, remember_me: true).tap do |browser_session|
82
+ # Store in both session and encrypted cookie for backward compatibility
76
83
  session[:session_token] = browser_session.token
84
+ cookies.encrypted[:session_token] = browser_session.token
77
85
  cookies[:remember_token] = token_manager.create_remember_token(password_credential)
78
86
  end
79
87
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: standard_id
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jaryl Sim
@@ -64,6 +64,7 @@ files:
64
64
  - README.md
65
65
  - Rakefile
66
66
  - app/assets/stylesheets/standard_id/application.css
67
+ - app/channels/concerns/standard_id/cable_authentication.rb
67
68
  - app/controllers/concerns/standard_id/api_authentication.rb
68
69
  - app/controllers/concerns/standard_id/inertia_rendering.rb
69
70
  - app/controllers/concerns/standard_id/inertia_support.rb