All integrations

Ruby Integration

Rails, Sinatra, and more

Turalogin fits naturally into Ruby controller actions or service objects. Start auth to send a magic link email, handle the callback when users click the link, and verify the token. Clean, idiomatic Ruby code that works with your existing authentication patterns.

  • Works with Rails, Sinatra, Hanami, and any Rack-based framework
  • Magic link flow with customizable callback URL
  • Fits into existing controller patterns
  • Compatible with Devise, Warden, or custom auth
  • Uses standard HTTP libraries (HTTParty, Faraday, Net::HTTP)

Implementation Examples

1. Environment Configuration

Set up your environment variables for local development and production.

.env
1# Your Turalogin API key from the dashboard
2TURALOGIN_API_KEY=tl_live_xxxxxxxxxxxxx
3
4# The URL where magic links will redirect to
5# Development:
6APP_LOGIN_VALIDATION_URL=http://localhost:3000/auth/callback
7
8# Production (update for your domain):
9# APP_LOGIN_VALIDATION_URL=https://myapp.com/auth/callback

2. Start Authentication (Rails)

Create a controller action to initiate authentication. This sends a magic link to the user's email.

app/controllers/auth_controller.rb
1class AuthController < ApplicationController
2 skip_before_action :authenticate_user!, only: [:start, :callback]
3
4 def start
5 email = params[:email]
6
7 unless email.present?
8 return render json: { error: "Email is required" }, status: :bad_request
9 end
10
11 response = HTTParty.post(
12 "https://api.turalogin.com/api/v1/auth/start",
13 headers: {
14 "Authorization" => "Bearer #{ENV['TURALOGIN_API_KEY']}",
15 "Content-Type" => "application/json"
16 },
17 body: {
18 email: email,
19 validationUrl: ENV['APP_LOGIN_VALIDATION_URL'] # Where the magic link redirects to
20 }.to_json
21 )
22
23 if response.success?
24 render json: { success: true, message: "Check your email for the login link" }
25 else
26 render json: response.parsed_response, status: response.code
27 end
28 end
29end

3. Handle Magic Link Callback

Create a callback action that receives the token from the magic link and verifies it.

app/controllers/auth_controller.rb
1def callback
2 token = params[:token]
3
4 unless token.present?
5 return redirect_to login_path, alert: "Invalid login link"
6 end
7
8 response = HTTParty.post(
9 "https://api.turalogin.com/api/v1/auth/verify",
10 headers: {
11 "Authorization" => "Bearer #{ENV['TURALOGIN_API_KEY']}",
12 "Content-Type" => "application/json"
13 },
14 body: { sessionId: token }.to_json
15 )
16
17 if response.success?
18 data = response.parsed_response
19 user_data = data["user"]
20
21 # Find or create user in your database
22 user = User.find_or_create_by(email: user_data["email"]) do |u|
23 u.turalogin_id = user_data["id"]
24 end
25
26 # Create session
27 session[:user_id] = user.id
28 session[:turalogin_token] = data["token"]
29
30 redirect_to dashboard_path, notice: "Successfully signed in!"
31 else
32 redirect_to login_path, alert: "Login link is invalid or expired"
33 end
34end
35
36def logout
37 reset_session
38 render json: { success: true }
39end

4. Turalogin Service Object

Extract Turalogin API calls into a service object for cleaner controllers.

app/services/turalogin_service.rb
1class TuraloginService
2 BASE_URL = "https://api.turalogin.com/api/v1"
3
4 class Error < StandardError
5 attr_reader :code, :status
6
7 def initialize(message, code:, status:)
8 super(message)
9 @code = code
10 @status = status
11 end
12 end
13
14 def initialize
15 @api_key = ENV.fetch("TURALOGIN_API_KEY")
16 @validation_url = ENV.fetch("APP_LOGIN_VALIDATION_URL")
17 end
18
19 def start_auth(email)
20 request("/auth/start", {
21 email: email,
22 validationUrl: @validation_url
23 })
24 end
25
26 def verify_token(token)
27 request("/auth/verify", { sessionId: token })
28 end
29
30 private
31
32 def request(endpoint, body)
33 response = HTTParty.post(
34 "#{BASE_URL}#{endpoint}",
35 headers: {
36 "Authorization" => "Bearer #{@api_key}",
37 "Content-Type" => "application/json"
38 },
39 body: body.to_json
40 )
41
42 unless response.success?
43 data = response.parsed_response
44 raise Error.new(
45 data["error"] || "Unknown error",
46 code: data["code"] || "UNKNOWN",
47 status: response.code
48 )
49 end
50
51 response.parsed_response
52 end
53end
54
55# Usage in controller:
56# @turalogin = TuraloginService.new
57# @turalogin.start_auth(params[:email])

5. Authentication Concern

Create a concern to handle authentication across controllers.

app/controllers/concerns/turalogin_auth.rb
1module TuraloginAuth
2 extend ActiveSupport::Concern
3
4 included do
5 before_action :authenticate_user!
6 helper_method :current_user, :user_signed_in?
7 end
8
9 def current_user
10 return @current_user if defined?(@current_user)
11
12 if session[:user_id]
13 @current_user = User.find_by(id: session[:user_id])
14 end
15 end
16
17 def user_signed_in?
18 current_user.present?
19 end
20
21 def authenticate_user!
22 unless user_signed_in?
23 respond_to do |format|
24 format.html { redirect_to login_path }
25 format.json {
26 render json: { error: "Authentication required" }, status: :unauthorized
27 }
28 end
29 end
30 end
31
32 def sign_in(user)
33 session[:user_id] = user.id
34 @current_user = user
35 end
36
37 def sign_out
38 reset_session
39 @current_user = nil
40 end
41end
42
43# Include in ApplicationController:
44# class ApplicationController < ActionController::Base
45# include TuraloginAuth
46# end

6. Error Handling

Handle Turalogin-specific errors in your controllers.

app/controllers/concerns/turalogin_error_handling.rb
1module TuraloginErrorHandling
2 extend ActiveSupport::Concern
3
4 included do
5 rescue_from TuraloginService::Error, with: :handle_turalogin_error
6 end
7
8 private
9
10 def handle_turalogin_error(error)
11 case error.code
12 when "INVALID_EMAIL"
13 render json: {
14 error: "Please provide a valid email address"
15 }, status: :bad_request
16
17 when "SESSION_EXPIRED"
18 render json: {
19 error: "Login link has expired. Please try again."
20 }, status: :bad_request
21
22 when "INVALID_TOKEN"
23 render json: {
24 error: "Invalid login link"
25 }, status: :bad_request
26
27 when "RATE_LIMITED"
28 render json: {
29 error: "Too many attempts. Please wait a moment."
30 }, status: :too_many_requests
31
32 else
33 Rails.logger.error("Turalogin error: #{error.message} (#{error.code})")
34 render json: {
35 error: "Authentication error. Please try again."
36 }, status: error.status || :internal_server_error
37 end
38 end
39end

Complete Rails Controller

A complete Rails controller with magic link authentication and proper error handling.

app/controllers/auth_controller.rb
1class AuthController < ApplicationController
2 include TuraloginErrorHandling
3
4 skip_before_action :authenticate_user!, only: [:start, :callback]
5 before_action :redirect_if_authenticated, only: [:start, :callback]
6
7 def start
8 email = params.require(:email)
9
10 turalogin.start_auth(email)
11
12 render json: { success: true, message: "Check your email for the login link" }
13 end
14
15 def callback
16 token = params[:token]
17
18 unless token.present?
19 return redirect_to login_path, alert: "Invalid login link"
20 end
21
22 result = turalogin.verify_token(token)
23 user_data = result["user"]
24
25 # Find or create user
26 user = User.find_or_create_by!(email: user_data["email"]) do |u|
27 u.turalogin_id = user_data["id"]
28 end
29
30 # Update last sign in
31 user.update!(last_sign_in_at: Time.current)
32
33 # Create session
34 sign_in(user)
35 session[:turalogin_token] = result["token"]
36
37 redirect_to dashboard_path, notice: "Successfully signed in!"
38 rescue TuraloginService::Error => e
39 redirect_to login_path, alert: "Login link is invalid or expired"
40 end
41
42 def logout
43 sign_out
44 render json: { success: true }
45 end
46
47 def me
48 render json: {
49 user: current_user.as_json(only: [:id, :email, :created_at])
50 }
51 end
52
53 private
54
55 def turalogin
56 @turalogin ||= TuraloginService.new
57 end
58
59 def redirect_if_authenticated
60 if user_signed_in?
61 respond_to do |format|
62 format.html { redirect_to dashboard_path }
63 format.json {
64 render json: { error: "Already authenticated" }, status: :forbidden
65 }
66 end
67 end
68 end
69end
70
71# Routes (config/routes.rb):
72# Rails.application.routes.draw do
73# post 'auth/start', to: 'auth#start'
74# get 'auth/callback', to: 'auth#callback'
75# delete 'auth/logout', to: 'auth#logout'
76# get 'auth/me', to: 'auth#me'
77# end

Ready to integrate?

Create your Turalogin account and get your API key in minutes.