SolRengine Auth

Solana wallet authentication for Ruby on Rails. Sign in with any Wallet Standard compatible wallet (Phantom, Solflare, Backpack, Jupiter, etc.) using SIWS (Sign In With Solana).

Part of the SolRengine framework.

Install

Add to your Gemfile:

gem "solrengine-auth"

Run the generator:

rails generate solrengine:auth:install
rails db:prepare

This adds:

  • wallet_address, nonce, nonce_expires_at columns to your User model
  • Authenticatable concern included in User
  • ControllerHelpers concern included in ApplicationController
  • Routes mounted at /auth (login, nonce, verify, logout)
  • Configuration initializer

Setup

Install the JavaScript dependencies:

yarn add @wallet-standard/app @solana/wallet-standard-features

Register the wallet Stimulus controller in your app/javascript/controllers/index.js:

import WalletController from "solrengine/auth/wallet_controller"
application.register("wallet", WalletController)

Configuration

# config/initializers/solrengine_auth.rb
Solrengine::Auth.configure do |config|
  config.domain = ENV.fetch("APP_DOMAIN", "localhost")
  config.nonce_ttl = 5.minutes
  config.after_sign_out_path = "/"

  # The model class used for wallet authentication (String or Class).
  # config.user_class = "User"

  # Chain ID shown in the wallet sign-in message.
  # Defaults to ENV["SOLANA_NETWORK"] or "mainnet".
  # config.chain_id = "devnet"
end

How It Works

  1. User clicks "Connect Wallet" -- Stimulus discovers installed wallets via Wallet Standard
  2. User selects a wallet -- extension popup opens
  3. Rails generates a SIWS message with a nonce (POST /auth/nonce)
  4. Wallet signs the message (Ed25519)
  5. Rails verifies the signature, validates the nonce, and creates a session (POST /auth/verify)

No passwords. No emails. The wallet is the identity.

Usage in Controllers

class DashboardController < ApplicationController
  before_action :authenticate!

  def show
    @wallet_address = current_user.wallet_address
  end
end

current_user, logged_in?, and authenticate! are provided by the Solrengine::Auth::Concerns::ControllerHelpers concern, which the generator includes in your ApplicationController.

Standalone Usage

The verifier can be used without Rails:

require "solrengine/auth"

verifier = Solrengine::Auth::SiwsVerifier.new(
  wallet_address: "Abc...xyz",
  message: siws_message,
  signature: signature_bytes,
  domain: "myapp.com",
  expected_nonce: user.nonce  # bind to server-issued nonce (recommended)
)

verifier.verify  # => true/false
verifier.verify! # => true or raises VerificationError

Always pass expected_nonce: when verifying a live sign-in. Without it, the verifier accepts any syntactically-valid nonce in the signed message, which makes captured (message, signature) pairs replayable as long as the wallet still has any fresh nonce on the server. The bundled Solrengine::Auth::SessionsController does this for you; apps that build their own controller must do it themselves.

License

MIT