Remember that we concented.
This commit is contained in:
@@ -82,6 +82,30 @@ class OidcController < ApplicationController
|
||||
return
|
||||
end
|
||||
|
||||
requested_scopes = scope.split(" ")
|
||||
|
||||
# Check if user has already granted consent for these scopes
|
||||
existing_consent = user.has_oidc_consent?(@application, requested_scopes)
|
||||
if existing_consent
|
||||
# User has already consented, generate authorization code directly
|
||||
code = SecureRandom.urlsafe_base64(32)
|
||||
auth_code = OidcAuthorizationCode.create!(
|
||||
application: @application,
|
||||
user: user,
|
||||
code: code,
|
||||
redirect_uri: redirect_uri,
|
||||
scope: scope,
|
||||
nonce: nonce,
|
||||
expires_at: 10.minutes.from_now
|
||||
)
|
||||
|
||||
# Redirect back to client with authorization code
|
||||
redirect_uri = "#{redirect_uri}?code=#{code}"
|
||||
redirect_uri += "&state=#{state}" if state.present?
|
||||
redirect_to redirect_uri, allow_other_host: true
|
||||
return
|
||||
end
|
||||
|
||||
# Store OAuth parameters for consent page
|
||||
session[:oauth_params] = {
|
||||
client_id: client_id,
|
||||
@@ -93,7 +117,7 @@ class OidcController < ApplicationController
|
||||
|
||||
# Render consent page
|
||||
@redirect_uri = redirect_uri
|
||||
@scopes = scope.split(" ")
|
||||
@scopes = requested_scopes
|
||||
render :consent
|
||||
end
|
||||
|
||||
@@ -120,6 +144,22 @@ class OidcController < ApplicationController
|
||||
application = Application.find_by(client_id: client_id, app_type: "oidc")
|
||||
user = Current.session.user
|
||||
|
||||
# Record user consent
|
||||
requested_scopes = oauth_params['scope'].split(' ')
|
||||
OidcUserConsent.upsert(
|
||||
{
|
||||
user: user,
|
||||
application: application,
|
||||
scopes_granted: requested_scopes.join(' '),
|
||||
granted_at: Time.current
|
||||
},
|
||||
unique_by: [:user_id, :application_id],
|
||||
update_columns: {
|
||||
scopes_granted: requested_scopes.join(' '),
|
||||
granted_at: Time.current
|
||||
}
|
||||
)
|
||||
|
||||
# Generate authorization code
|
||||
code = SecureRandom.urlsafe_base64(32)
|
||||
auth_code = OidcAuthorizationCode.create!(
|
||||
|
||||
@@ -5,6 +5,7 @@ class Application < ApplicationRecord
|
||||
has_many :allowed_groups, through: :application_groups, source: :group
|
||||
has_many :oidc_authorization_codes, dependent: :destroy
|
||||
has_many :oidc_access_tokens, dependent: :destroy
|
||||
has_many :oidc_user_consents, dependent: :destroy
|
||||
has_many :application_roles, dependent: :destroy
|
||||
has_many :user_role_assignments, through: :application_roles
|
||||
|
||||
|
||||
34
app/models/oidc_user_consent.rb
Normal file
34
app/models/oidc_user_consent.rb
Normal file
@@ -0,0 +1,34 @@
|
||||
class OidcUserConsent < ApplicationRecord
|
||||
belongs_to :user
|
||||
belongs_to :application
|
||||
|
||||
validates :user, :application, :scopes_granted, :granted_at, presence: true
|
||||
validates :user_id, uniqueness: { scope: :application_id }
|
||||
|
||||
before_validation :set_granted_at, on: :create
|
||||
|
||||
# Parse scopes_granted into an array
|
||||
def scopes
|
||||
scopes_granted.split(' ')
|
||||
end
|
||||
|
||||
# Set scopes from an array
|
||||
def scopes=(scope_array)
|
||||
self.scopes_granted = Array(scope_array).uniq.join(' ')
|
||||
end
|
||||
|
||||
# Check if this consent covers the requested scopes
|
||||
def covers_scopes?(requested_scopes)
|
||||
requested = Array(requested_scopes).map(&:to_s)
|
||||
granted = scopes
|
||||
|
||||
# All requested scopes must be included in granted scopes
|
||||
(requested - granted).empty?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_granted_at
|
||||
self.granted_at ||= Time.current
|
||||
end
|
||||
end
|
||||
@@ -5,6 +5,7 @@ class User < ApplicationRecord
|
||||
has_many :groups, through: :user_groups
|
||||
has_many :user_role_assignments, dependent: :destroy
|
||||
has_many :application_roles, through: :user_role_assignments
|
||||
has_many :oidc_user_consents, dependent: :destroy
|
||||
|
||||
# Token generation for passwordless flows
|
||||
generates_token_for :invitation, expires_in: 7.days
|
||||
@@ -73,6 +74,12 @@ class User < ApplicationRecord
|
||||
JSON.parse(backup_codes)
|
||||
end
|
||||
|
||||
def has_oidc_consent?(application, requested_scopes)
|
||||
oidc_user_consents
|
||||
.where(application: application)
|
||||
.find { |consent| consent.covers_scopes?(requested_scopes) }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def generate_backup_codes
|
||||
|
||||
Reference in New Issue
Block a user