Switch to diy oauth
This commit is contained in:
83
app/controllers/oidc_auth_controller.rb
Normal file
83
app/controllers/oidc_auth_controller.rb
Normal file
@@ -0,0 +1,83 @@
|
||||
class OidcAuthController < ApplicationController
|
||||
allow_unauthenticated_access only: [:authorize, :callback]
|
||||
|
||||
# POST /auth/oidc - Initiate OIDC flow
|
||||
def authorize
|
||||
redirect_to oidc_client.authorization_uri(
|
||||
scope: [:openid, :email, :profile],
|
||||
state: generate_state_token,
|
||||
nonce: generate_nonce
|
||||
), allow_other_host: true
|
||||
end
|
||||
|
||||
# GET /auth/oidc/callback - Handle provider callback
|
||||
def callback
|
||||
# Verify state token
|
||||
unless valid_state_token?(params[:state])
|
||||
redirect_to new_session_path, alert: "Invalid authentication state"
|
||||
return
|
||||
end
|
||||
|
||||
# Exchange authorization code for tokens
|
||||
oidc_client.authorization_code = params[:code]
|
||||
access_token = oidc_client.access_token!
|
||||
|
||||
# Get user info
|
||||
user_info = access_token.userinfo!
|
||||
|
||||
# Find user by email
|
||||
user = User.find_by(email_address: user_info.email)
|
||||
|
||||
unless user
|
||||
redirect_to new_session_path, alert: "No user found with email: #{user_info.email}"
|
||||
return
|
||||
end
|
||||
|
||||
# Update role based on OIDC groups if present
|
||||
if user_info.respond_to?(:groups) && user_info.groups.present?
|
||||
user.update_role_from_oidc_groups(user_info.groups)
|
||||
end
|
||||
|
||||
start_new_session_for(user)
|
||||
redirect_to root_path, notice: "Successfully signed in via OIDC"
|
||||
|
||||
rescue OpenIDConnect::Exception, Rack::OAuth2::Client::Error => e
|
||||
Rails.logger.error "OIDC authentication failed: #{e.message}"
|
||||
redirect_to new_session_path, alert: "Authentication failed: #{e.message}"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def oidc_client
|
||||
@oidc_client ||= begin
|
||||
discovery = OpenIDConnect::Discovery::Provider::Config.discover!(ENV['OIDC_DISCOVERY_URL'])
|
||||
|
||||
OpenIDConnect::Client.new(
|
||||
identifier: ENV['OIDC_CLIENT_ID'],
|
||||
secret: ENV['OIDC_CLIENT_SECRET'],
|
||||
redirect_uri: ENV['OIDC_REDIRECT_URI'] || oidc_callback_url,
|
||||
authorization_endpoint: discovery.authorization_endpoint,
|
||||
token_endpoint: discovery.token_endpoint,
|
||||
userinfo_endpoint: discovery.userinfo_endpoint
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def generate_state_token
|
||||
token = SecureRandom.hex(32)
|
||||
session[:oidc_state] = token
|
||||
token
|
||||
end
|
||||
|
||||
def generate_nonce
|
||||
SecureRandom.hex(32)
|
||||
end
|
||||
|
||||
def valid_state_token?(state)
|
||||
state.present? && session[:oidc_state] == state
|
||||
end
|
||||
|
||||
def oidc_callback_url
|
||||
"#{request.base_url}/auth/oidc/callback"
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user