22
33module Solrengine
44 module Auth
5+ # Handles Solana wallet authentication sessions: nonce generation,
6+ # SIWS signature verification, and session lifecycle.
57 class SessionsController < ApplicationController
6-
78 def new
89 # Renders the wallet connect view
910 end
@@ -12,68 +13,81 @@ def nonce
1213 wallet_address = params [ :wallet_address ]
1314
1415 unless wallet_address . match? ( Concerns ::Authenticatable ::SOLANA_ADDRESS_FORMAT )
15- return render json : { error : " Invalid wallet address" } , status : :unprocessable_entity
16+ return render json : { error : ' Invalid wallet address' } , status : :unprocessable_entity
1617 end
1718
18- user_class = _user_class
19- user = user_class . find_or_initialize_by ( wallet_address : wallet_address )
20- user . generate_nonce! if user . persisted?
21- user . save! unless user . persisted?
22-
23- domain = Solrengine ::Auth . configuration . domain
24- message = SiwsMessageBuilder . new (
25- domain : domain ,
26- wallet_address : wallet_address ,
27- nonce : user . nonce ,
28- uri : request . base_url
29- ) . build
19+ user = find_or_create_user ( wallet_address )
20+ message = build_nonce_message ( wallet_address , user . nonce )
3021
3122 render json : { message : message , nonce : user . nonce }
3223 end
3324
3425 def create
35- wallet_address = params [ :wallet_address ]
36- message = params [ :message ]
37- signature = params [ :signature ]
38-
39- user = _user_class . find_by ( wallet_address : wallet_address )
26+ user = _user_class . find_by ( wallet_address : params [ :wallet_address ] )
4027
4128 unless user &.nonce_valid?
42- return render json : { error : " Authentication expired. Please try again." } , status : :unprocessable_entity
29+ return render json : { error : ' Authentication expired. Please try again.' } , status : :unprocessable_entity
4330 end
4431
45- verifier = SiwsVerifier . new (
32+ return render_verification_failed unless verify_signature ( user )
33+ return render_nonce_mismatch unless nonce_matches? ( params [ :message ] , user )
34+
35+ complete_authentication ( user )
36+ end
37+
38+ def destroy
39+ reset_session
40+ redirect_to Solrengine ::Auth . configuration . after_sign_out_path , notice : 'Disconnected'
41+ end
42+
43+ private
44+
45+ def _user_class
46+ Solrengine ::Auth . configuration . user_model
47+ end
48+
49+ def find_or_create_user ( wallet_address )
50+ user = _user_class . find_or_initialize_by ( wallet_address : wallet_address )
51+ user . generate_nonce! if user . persisted?
52+ user . save! unless user . persisted?
53+ user
54+ end
55+
56+ def build_nonce_message ( wallet_address , nonce )
57+ SiwsMessageBuilder . new (
58+ domain : Solrengine ::Auth . configuration . domain ,
4659 wallet_address : wallet_address ,
47- message : message ,
48- signature : signature
49- )
60+ nonce : nonce ,
61+ uri : request . base_url
62+ ) . build
63+ end
5064
51- unless verifier . verify
52- return render json : { error : "Signature verification failed" } , status : :unauthorized
53- end
65+ def verify_signature ( user )
66+ SiwsVerifier . new (
67+ wallet_address : user . wallet_address ,
68+ message : params [ :message ] ,
69+ signature : params [ :signature ]
70+ ) . verify
71+ end
5472
55- # Verify the nonce in the signed message matches the database nonce
73+ def nonce_matches? ( message , user )
5674 message_nonce = message . match ( /Nonce: ([a-f0-9]+)/ ) &.captures &.first
57- unless message_nonce . present? && ActiveSupport ::SecurityUtils . secure_compare ( message_nonce , user . nonce )
58- return render json : { error : "Nonce mismatch" } , status : :unauthorized
59- end
75+ message_nonce . present? && ActiveSupport ::SecurityUtils . secure_compare ( message_nonce , user . nonce )
76+ end
6077
78+ def complete_authentication ( user )
6179 user . generate_nonce!
62-
6380 reset_session
6481 session [ :user_id ] = user . id
6582 render json : { success : true , wallet_address : user . wallet_address }
6683 end
6784
68- def destroy
69- reset_session
70- redirect_to Solrengine ::Auth . configuration . after_sign_out_path , notice : "Disconnected"
85+ def render_verification_failed
86+ render json : { error : 'Signature verification failed' } , status : :unauthorized
7187 end
7288
73- private
74-
75- def _user_class
76- Solrengine ::Auth . configuration . user_model
89+ def render_nonce_mismatch
90+ render json : { error : 'Nonce mismatch' } , status : :unauthorized
7791 end
7892 end
7993 end
0 commit comments