### Using the Rails Debugger Source: https://github.com/wmlele/devise-otp/blob/master/test/dummy/README.rdoc Example of how to use the debugger in a Rails controller by inserting the 'debugger' keyword. This requires starting the server with the --debugger flag and installing the ruby-debug gem. ```ruby class WeblogController < ActionController::Base def index @posts = Post.all debugger end end ``` -------------------------------- ### Starting the Rails Development Server Source: https://github.com/wmlele/devise-otp/blob/master/test/dummy/README.rdoc Command to change into the application directory and start the Rails development server. Use --help for options. ```bash cd myapp; rails server ``` -------------------------------- ### Install Devise OTP and Migrate Database Source: https://context7.com/wmlele/devise-otp/llms.txt Installs the Devise OTP generator and runs database migrations to add necessary columns for OTP functionality. This is the initial setup step for integrating Devise OTP into a Rails application. ```bash rails g devise_otp:install rails g devise_otp User rake db:migrate ``` -------------------------------- ### Install Gems for All Ruby/Rails Versions with Appraisal Source: https://github.com/wmlele/devise-otp/blob/master/README.md This command is used to install all necessary gems for all specified Ruby/Rails versions when using Appraisal. This is crucial for testing the gem against different environments, especially if older Ruby/Rails versions are involved. ```bash bundle exec appraisal install ``` -------------------------------- ### Install Devise OTP Gem Source: https://github.com/wmlele/devise-otp/blob/master/README.md Add the devise-otp gem to your application's Gemfile and install it using Bundler. Alternatively, you can install it directly using the gem command. ```ruby gem "devise-otp" $ bundle # or $ gem install devise-otp ``` -------------------------------- ### Run Rails Console or Server in Dummy App Source: https://github.com/wmlele/devise-otp/blob/master/README.md These commands start the Rails console or server for the dummy application. They are used for interactive development and testing within the devise-otp environment. ```bash rails c rails s ``` -------------------------------- ### Interacting with Model Objects in Debugger (IRB) Source: https://github.com/wmlele/devise-otp/blob/master/test/dummy/README.rdoc Example commands to inspect and modify model objects within the Rails debugger session, which presents an IRB prompt. ```irb >> @posts.inspect => "[#nil, \"body\"=>nil, \"id\"=>\"1\"}>, #\"Rails\", \"body\"=>\"Only ten..\", \"id\"=>\"2\"}>]" >> @posts.first.title = "hello from a debugger" => "hello from a debugger" >> f = @posts.first => #nil, "body"=>nil, "id"=>"1"}> >> f. Display all 152 possibilities? (y or n) ``` -------------------------------- ### Logging Custom Messages in Rails Controllers (Ruby) Source: https://github.com/wmlele/devise-otp/blob/master/test/dummy/README.rdoc Example of how to log custom messages within a Rails controller using the Ruby logger class. This is useful for debugging runtime information. ```ruby class WeblogController < ActionController::Base def destroy @weblog = Weblog.find(params[:id]) @weblog.destroy logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!") end end ``` -------------------------------- ### Generate Devise OTP Configuration and Model Additions Source: https://github.com/wmlele/devise-otp/blob/master/README.md Run the devise_otp:install generator to add necessary configuration options to Devise's initializer. Then, run the generator again with your model name to set up Devise OTP additions for your user model. Finally, migrate your database. ```ruby rails g devise_otp:install rails g devise_otp MODEL rake db:migrate ``` -------------------------------- ### Validate OTP Tokens with Recovery Support Source: https://context7.com/wmlele/devise-otp/llms.txt Provides examples of validating both time-based OTP tokens from authenticator apps and recovery tokens for emergency access within a controller or service. It also shows how to generate and check the validity of OTP challenges. ```ruby # In controller or service user = User.find_by(email: 'user@example.com') # Validate time-based token (from authenticator app) if user.valid_otp_token?('123456') sign_in(user) redirect_to dashboard_path else flash[:alert] = 'Invalid OTP token' render :otp_challenge end # Validate recovery token (emergency access) if user.valid_otp_recovery_token?('9876543210') sign_in(user) # Recovery counter is automatically incremented flash[:notice] = 'Logged in using recovery token' redirect_to dashboard_path end # Generate OTP challenge for user session challenge = user.generate_otp_challenge!(3.minutes) # => "a1b2c3d4e5f6..." # Check if challenge is still valid user.otp_challenge_valid? # => true/false ``` -------------------------------- ### Enforce Mandatory User OTP in Rails Controller Source: https://github.com/wmlele/devise-otp/blob/master/README.md This code snippet demonstrates how to enforce mandatory OTP for users in a Rails controller. It uses the `ensure_mandatory_user_otp!` method, which redirects users to the OTP setup form if not already configured. This can be included alongside other `before_action` filters. ```ruby before_action :authenticate_user! before_action :ensure_mandatory_user_otp! ``` -------------------------------- ### Creating a New Rails Application Source: https://github.com/wmlele/devise-otp/blob/master/test/dummy/README.rdoc Command to generate a new Rails application. This is the initial step for setting up a Rails project. ```bash rails new myapp ``` -------------------------------- ### Migrate Test Database for Devise-OTP Source: https://github.com/wmlele/devise-otp/blob/master/README.md This command prepares the test environment's database by dropping, creating, and migrating it. It's essential before running tests to ensure the database schema is up-to-date. ```bash RAILS_ENV=test rails db:drop db:create db:migrate ``` -------------------------------- ### Check Ruby Syntax and Formatting with Rubocop Source: https://github.com/wmlele/devise-otp/blob/master/README.md This command uses Rubocop to check and enforce Ruby syntax and formatting standards across the project. It helps maintain code quality and consistency. ```bash ./bin/rubocop ``` -------------------------------- ### Run Devise-OTP Tests Source: https://github.com/wmlele/devise-otp/blob/master/README.md This command executes all tests for the devise-otp gem against the current Ruby/Rails configuration. It's the primary method for verifying the gem's functionality and stability. ```bash rake test ``` -------------------------------- ### Lint ERB Views with ERB Lint Source: https://github.com/wmlele/devise-otp/blob/master/README.md This command uses ERB Lint to check and enforce formatting and best practices for ERB view files. The `-a --lint-all` flags enable automatic correction and linting of all rules. ```bash ./bin/erb_lint -a --lint-all ``` -------------------------------- ### Reset Database in Devise-OTP Dummy App Source: https://github.com/wmlele/devise-otp/blob/master/README.md This command resets and seeds the database for the devise-otp dummy application. It ensures a clean state for development and testing by dropping, creating, and migrating the database. ```bash rails db:reset ``` -------------------------------- ### QR Code Generation for Authenticator App - ERB and Ruby Source: https://context7.com/wmlele/devise-otp/llms.txt Generates QR codes for setting up authenticator apps and displays the secret key. The ERB view uses the `otp_authenticator_token_image` helper, while the Ruby controller demonstrates generating the QR code using the `rqrcode` gem. ```ERB

Enable Two-Factor Authentication

Scan this QR code with your authenticator app:

<%= otp_authenticator_token_image(resource) %>

Or enter this secret manually: <%= resource.otp_auth_secret %>

<%= form_for(resource, url: user_otp_token_path, method: :put) do |f| %> <%= f.label :confirmation_code, "Enter the 6-digit code from your app" %> <%= f.text_field :confirmation_code, autofocus: true, autocomplete: 'off' %> <%= f.submit "Enable OTP" %> <% end %> ``` ```Ruby # Generate QR code in controller class CustomOtpController < ApplicationController def setup @user = current_user @user.populate_otp_secrets! # Get provisioning URI @provisioning_uri = @user.otp_provisioning_uri # Generate QR code as SVG require 'rqrcode' qr_code = RQRCode::QRCode.new(@provisioning_uri) @qr_svg = qr_code.as_svg(module_size: 5, viewbox: true, use_path: true) end end ``` -------------------------------- ### Generate and Manage Recovery Tokens Source: https://context7.com/wmlele/devise-otp/llms.txt Demonstrates how to generate a specified number of OTP recovery tokens for emergency access, display them to the user, and validate their usage. It also includes how to reset all OTP-related fields for a user. ```ruby # Generate next N recovery tokens user = User.find(1) tokens = user.next_otp_recovery_tokens(10) # => {0=>"1234567890", 1=>"0987654321", 2=>"5678901234", ...} # Display tokens to user for safekeeping tokens.each do |index, token| puts "#{index + 1}. #{token}" end # Recovery counter tracks used tokens user.otp_recovery_counter # => 0 user.validate_otp_recovery_token('1234567890') # => true user.otp_recovery_counter # => 1 (incremented after use) # Reset OTP completely (clears all tokens and secrets) user.clear_otp_fields! user.otp_auth_secret # => nil user.otp_recovery_secret # => nil user.otp_enabled # => false ``` -------------------------------- ### Configure Devise OTP Settings Source: https://context7.com/wmlele/devise-otp/llms.txt Configures various settings for Devise OTP, such as mandatory OTP enforcement, authentication timeout, drift window for clock synchronization, and trusted browser persistence. These options are set in the Devise initializer file. ```ruby # config/initializers/devise.rb Devise.setup do |config| config.otp_mandatory = false config.otp_authentication_timeout = 3.minutes config.otp_drift_window = 3 config.otp_credentials_refresh = 15.minutes config.otp_recovery_tokens = 10 config.otp_trust_persistence = 1.month config.otp_issuer = 'MyApplication' config.otp_controller_path = 'devise' end ``` -------------------------------- ### Include Devise OTP CSS Source: https://github.com/wmlele/devise-otp/blob/master/README.md To use the default CSS for Devise OTP, require the `devise-otp.css` file in your application's CSS manifest. Alternatively, you can copy the styles directly into your project. ```css *= require devise-otp ``` -------------------------------- ### OTP Credentials Controller - Ruby Source: https://context7.com/wmlele/devise-otp/llms.txt Handles OTP authentication flow including trusted browser management and revocation. It checks if a browser is trusted, allows users to trust their current browser, and provides methods to revoke trust for single browsers or all trusted browsers. ```Ruby class ApplicationController < ActionController::Base include DeviseOtpAuthenticatable::Controllers::Helpers def after_otp_success # Check if browser is already trusted if is_otp_trusted_browser_for?(current_user) redirect_to dashboard_path return end # Set current browser as trusted if user requested if params[:trust_device] == '1' otp_set_trusted_device_for(current_user) flash[:notice] = 'This browser is now trusted for 30 days' end redirect_to dashboard_path end def revoke_trust # Clear trust for current browser otp_clear_trusted_device_for(current_user) flash[:notice] = 'Browser trust removed' redirect_to otp_token_path end def reset_all_trust # Reset persistence seed (invalidates all trusted browsers) otp_reset_persistence_for(current_user) flash[:notice] = 'All trusted browsers have been revoked' redirect_to otp_token_path end end ``` -------------------------------- ### Routes Configuration for Devise OTP - Ruby Source: https://context7.com/wmlele/devise-otp/llms.txt Configures routes for OTP-related actions within a Rails application. The `devise_otp` gem automatically adds necessary routes. This snippet lists the available OTP routes and credential challenge routes. ```Ruby # config/routes.rb Rails.application.routes.draw do devise_for :users # OTP routes are automatically added by devise_otp end # Available OTP routes: # GET /users/otp/token - Show OTP status # GET /users/otp/token/edit - Setup/enable OTP # PUT /users/otp/token - Confirm OTP setup # DELETE /users/otp/token - Disable OTP # GET /users/otp/token/recovery - View recovery tokens # POST /users/otp/token/reset - Reset OTP (generate new secrets) # OTP credential challenge routes: # GET /users/otp/credential - Show OTP challenge # PUT /users/otp/credential - Submit OTP token # GET /users/otp/credential/refresh - Refresh credentials # PUT /users/otp/credential/refresh - Submit password refresh # Trusted device routes (if enabled): # POST /users/otp/persistence - Set browser as trusted # DELETE /users/otp/persistence - Remove browser trust # DELETE /users/otp/persistence/reset - Revoke all trusted browsers ``` -------------------------------- ### Database Migration for Users Table (Ruby) Source: https://context7.com/wmlele/devise-otp/llms.txt Adds necessary columns to the users table for Devise OTP functionality. Includes fields for OTP secrets, enablement status, failed attempts, and session challenges. Also adds indexes for efficient querying. ```ruby class DeviseOtpAddToUsers < ActiveRecord::Migration[7.0] def self.up change_table :users do |t| t.string :otp_auth_secret t.string :otp_recovery_secret t.boolean :otp_enabled, default: false, null: false t.boolean :otp_mandatory, default: false, null: false t.datetime :otp_enabled_on t.integer :otp_failed_attempts, default: 0, null: false t.integer :otp_recovery_counter, default: 0, null: false t.string :otp_persistence_seed t.string :otp_session_challenge t.datetime :otp_challenge_expires end add_index :users, :otp_session_challenge, unique: true add_index :users, :otp_challenge_expires end def self.down change_table :users do |t| t.remove :otp_auth_secret, :otp_recovery_secret, :otp_enabled, :otp_mandatory, :otp_enabled_on, :otp_session_challenge, :otp_challenge_expires, :otp_failed_attempts, :otp_recovery_counter, :otp_persistence_seed end end end ``` -------------------------------- ### Devise OTP Configuration Options Source: https://github.com/wmlele/devise-otp/blob/master/README.md These options can be added to your `config/initializers/devise.rb` file to customize Devise OTP behavior. They control aspects like OTP enforcement, timeouts, drift windows, recovery tokens, and trusted browser persistence. ```ruby config.otp_mandatory = true config.otp_authentication_timeout = 3.minutes config.otp_drift_window = 3 config.otp_credentials_refresh = 15.minutes config.otp_recovery_tokens = 10 config.otp_trust_persistence = 1.month config.otp_issuer = "My Rails App" config.otp_controller_path = 'devise' ``` -------------------------------- ### OTP Challenges Controller Logic (Ruby) Source: https://context7.com/wmlele/devise-otp/llms.txt Handles OTP challenge display and verification. It finds the user based on the challenge and verifies the provided OTP token. Handles invalid tokens by incrementing failed attempts and rendering the show view with an error. ```ruby class OtpChallengesController < ApplicationController def show @challenge = params[:challenge] @user = User.find_valid_otp_challenge(@challenge) unless @user flash[:alert] = 'Invalid or expired OTP session' redirect_to new_user_session_path end end def verify @user = User.find_valid_otp_challenge(params[:challenge]) token = params[:token] if @user&.validate_otp_token(token) sign_in(@user) @user.otp_failed_attempts = 0 @user.save # Handle remember_me remember_me(@user) if session[:remember_me] == '1' redirect_to dashboard_path else @user.increment!(:otp_failed_attempts) flash.now[:alert] = 'Invalid OTP code' render :show, status: :unprocessable_entity end end end ``` -------------------------------- ### Eject Devise OTP Views Source: https://github.com/wmlele/devise-otp/blob/master/README.md Use the `devise_otp:views` generator to customize the default view files for Devise OTP. These files are located in `app/views/devise` by default. You can configure the controller path in your initializers if needed. ```ruby rails g devise_otp:views ``` -------------------------------- ### Custom OTP Challenge Flow - Ruby Source: https://context7.com/wmlele/devise-otp/llms.txt Implements a custom OTP authentication flow by overriding the `SessionsController`. This allows for custom logic before signing in a user, such as generating an OTP challenge and redirecting to an OTP verification page. ```Ruby # app/controllers/sessions_controller.rb class SessionsController < Devise::SessionsController def create user = User.find_by(email: params[:user][:email]) if user&.valid_password?(params[:user][:password]) if user.otp_enabled? # Generate OTP challenge challenge = user.generate_otp_challenge!(3.minutes) # Store remember_me preference session[:remember_me] = params[:user][:remember_me] # Redirect to OTP challenge page redirect_to user_otp_credential_path(challenge: challenge) else # No OTP required, sign in normally sign_in(user) redirect_to after_sign_in_path_for(user) end else flash[:alert] = 'Invalid email or password' render :new, status: :unprocessable_entity end end end ``` -------------------------------- ### Integrate Devise OTP into User Model Source: https://context7.com/wmlele/devise-otp/llms.txt Adds the `:otp_authenticatable` strategy to the Devise User model, enabling OTP authentication. This snippet also demonstrates methods for enabling/disabling OTP, generating secrets, retrieving provisioning URIs for QR codes, and validating OTP tokens. ```ruby # app/models/user.rb class User < ApplicationRecord devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, :otp_authenticatable end # Enable OTP for a user user = User.find(1) user.populate_otp_secrets! # Generate secrets if not present user.enable_otp! # Enable OTP authentication # Check OTP status user.otp_enabled # => true user.otp_enabled_on # => 2025-12-25 10:30:00 UTC # Get provisioning URI for QR code generation uri = user.otp_provisioning_uri # => "otpauth://totp/MyApplication:user@example.com?secret=BASE32SECRET&issuer=MyApplication" # Validate time-based OTP token user.validate_otp_token('123456') # => true/false # Disable OTP user.disable_otp! ``` -------------------------------- ### Mandatory OTP Enforcement - Ruby Source: https://context7.com/wmlele/devise-otp/llms.txt Ensures users are enrolled in OTP before accessing protected resources. This can be configured globally in an initializer or on a per-user basis. It uses `before_action` filters to check OTP status. ```Ruby # app/controllers/posts_controller.rb class PostsController < ApplicationController before_action :authenticate_user! before_action :ensure_mandatory_user_otp! def index # User must have OTP enabled to reach this action @posts = current_user.posts end end # Check if user requires OTP enrollment user = current_user if mandatory_otp_missing_on?(user) redirect_to edit_user_otp_token_path return end # Set OTP as mandatory globally (in initializer) # config.otp_mandatory = true # Or set per-user basis user = User.find(1) user.update(otp_mandatory: true) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.