Authentication Flow
ThibautBaissac/rails_ai_agents
Implements authentication using Rails 8 built-in generator. An agent skill from ThibautBaissac/rails_ai_agents.
Implements custom passwordless authentication without Devise.
$ npx skills add dilolabs/nosia --skill auth-setup -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install dilolabs/nosia auth-setup --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/dilolabs/nosia.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.vibe/skills/auth-setup .claude/skills/auth-setup && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "auth-setup" agent skill from https://github.com/dilolabs/nosia/tree/main/.vibe/skills/auth-setup into .claude/skills/auth-setup/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "auth-setup", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/dilolabs/nosia/tree/main/.vibe/skills/auth-setupType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add dilolabs/nosia --skill auth-setup -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install dilolabs/nosia auth-setup --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/dilolabs/nosia.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.vibe/skills/auth-setup .agents/skills/auth-setup && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "auth-setup" agent skill from https://github.com/dilolabs/nosia/tree/main/.vibe/skills/auth-setup into .agents/skills/auth-setup/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "auth-setup", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add dilolabs/nosia --skill auth-setup -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install dilolabs/nosia auth-setup --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/dilolabs/nosia.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.vibe/skills/auth-setup .cursor/skills/auth-setup && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "auth-setup" agent skill from https://github.com/dilolabs/nosia/tree/main/.vibe/skills/auth-setup into .cursor/skills/auth-setup/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "auth-setup", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/dilolabs/nosia.git --path .vibe/skills/auth-setup--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add dilolabs/nosia --skill auth-setup -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install dilolabs/nosia auth-setup --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/dilolabs/nosia.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.vibe/skills/auth-setup .gemini/skills/auth-setup && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "auth-setup" agent skill from https://github.com/dilolabs/nosia/tree/main/.vibe/skills/auth-setup into .gemini/skills/auth-setup/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "auth-setup", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install dilolabs/nosia auth-setupInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add dilolabs/nosia --skill auth-setup -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/dilolabs/nosia.git skills-src && mkdir -p .github/skills && cp -r skills-src/.vibe/skills/auth-setup .github/skills/auth-setup && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "auth-setup" agent skill from https://github.com/dilolabs/nosia/tree/main/.vibe/skills/auth-setup into .github/skills/auth-setup/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "auth-setup", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add dilolabs/nosia --skill auth-setup -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install dilolabs/nosia auth-setup --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/dilolabs/nosia.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.vibe/skills/auth-setup .opencode/skills/auth-setup && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "auth-setup" agent skill from https://github.com/dilolabs/nosia/tree/main/.vibe/skills/auth-setup into .opencode/skills/auth-setup/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "auth-setup", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
auth-setupImplements custom passwordless authentication without Devise.
Auth Setup is an agent skill from dilolabs/nosia. Implements custom passwordless authentication without Devise. Use when setting up authentication, login flows, session management, passkeys (WebAuthn), magic links, or password resets. Passkeys are the primary auth method; magic links are the fallback. WHEN NOT: For authorization/permissions (use controller concerns and role checks on User model). For multi-tenancy account scoping (see multi-tenant-setup skill).
Its SKILL.md is about 2.9k tokens, which your agent loads only when the skill is triggered. The skill folder holds 3 other files, including reference files (for example `references/auth-components.md` and `references/magic-links.md`). Compatibility notes: Ruby 3.3+, Rails 8.0+
It sits in Backend & APIs, covering Authentication. It works with Ruby on Rails. The repository describes itself as: Self-hosted AI RAG + MCP Platform. The licence is MIT.
7 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 0ef5e5d. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
railsFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Ruby 3.3+, Rails 8.0+
From compatibility in the SKILL.md frontmatter.
Auth Setup loads about 2.9k tokens when it runs, and up to ~6.8k if it reads all its reference files. Until then it costs about 107 tokens; SKILL.md has 515 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from dilolabs/nosia at commit 0ef5e5d, republished under its MIT licence (© dilolabs). 515 words, ~2,922 tokens.
.claude/skills/auth-setup/SKILL.md (or your agent's skills folder). This skill also uses 2 other files; get the full folder from GitHub.You are an expert Rails authentication architect specializing in building auth from scratch.
Auth is simple. Don't use Devise. A basic auth system is ~200 lines of code. You get full control, no bloat, easier modifications, and no gem version conflicts.
has_passkeys + optional password hash)ActionPack::Passkey)Tech Stack: Rails 8.2 (edge), ActionPack::Passkey (built-in WebAuthn), BCrypt for passwords (optional), has_secure_token
Pattern: Passkeys (WebAuthn) primary, magic links fallback, password optional for APIs
Session storage: Database (not cookies), token-based
bin/rails generate model Identity email_address:string password_digest:stringbin/rails test test/controllers/sessions_controller_test.rbbin/rails console then Identity.authenticate_by(email_address: "test@example.com")Identity (email, has_passkeys, optional password)
|-- has_many :passkeys (WebAuthn credentials, primary auth)
|-- has_many :sessions (token-based, database)
|-- has_many :magic_links (passwordless login fallback)
|-- has_one :user (app-specific profile data)
ActionPack::Passkey (credential_id, public_key, sign_count, transports)
Session (has_secure_token, 30-day expiry)
MagicLink (6-char code, 15-min expiry, one-time use)
Current (session, identity, user, account context)Rails.application.routes.draw do
resource :session do
scope module: :sessions do
resource :magic_link
resource :passkey, only: :create # Passkey authentication
end
end
# Passkey management (authenticated users)
namespace :my do
resource :passkey_challenge, only: :create # WebAuthn challenge endpoint
resources :passkeys, except: %i[ show new ] # Register, rename, remove
end
resource :signup, only: [:new, :create] # Optional
root "boards#index"
endNote: The ActionPack::Passkey railtie also auto-mounts a challenge endpoint at /rails/action_pack/passkey/challenge for the WebAuthn ceremony. The my/passkey_challenge route above overrides it with app-specific auth.
The sessions controller includes ActionPack::Passkey::Request and generates passkey authentication options on new so the sign-in page can offer passkey autofill (conditional mediation).
class SessionsController < ApplicationController
include ActionPack::Passkey::Request
allow_unauthenticated_access only: [:new, :create]
rate_limit to: 10, within: 3.minutes, only: :create
def new
@authentication_options = passkey_authentication_options # For passkey sign-in
end
def create
if identity = Identity.find_by(email_address: params[:email_address])
identity.send_magic_link
redirect_to new_session_path, notice: "Check your email for a sign-in link"
else
redirect_to new_session_path, alert: "No account found with that email"
end
end
def destroy
terminate_session
redirect_to root_path
end
endHandles the WebAuthn assertion ceremony when a user signs in with a passkey. The ActionPack::Passkey.authenticate method looks up the credential by ID, verifies the signature against the stored public key, and returns the passkey record (or nil).
class Sessions::PasskeysController < ApplicationController
include ActionPack::Passkey::Request
allow_unauthenticated_access
rate_limit to: 10, within: 3.minutes, only: :create
def create
if credential = ActionPack::Passkey.authenticate(passkey_authentication_params)
start_new_session_for credential.holder
redirect_to root_path
else
redirect_to new_session_path, alert: "That passkey didn't work. Try again."
end
end
endAuthenticated users register, rename, and remove their passkeys via the My::PasskeysController.
class My::PasskeysController < ApplicationController
include ActionPack::Passkey::Request
before_action :set_passkey, only: %i[ edit update destroy ]
def index
@passkeys = Current.identity.passkeys.order(name: :asc, created_at: :desc)
@registration_options = passkey_registration_options(holder: Current.identity)
end
def create
passkey = Current.identity.passkeys.register(passkey_registration_params)
redirect_to edit_my_passkey_path(passkey, created: true)
end
def edit; end
def update
@passkey.update!(params.expect(passkey: [ :name ]))
redirect_to my_passkeys_path
end
def destroy
@passkey.destroy!
redirect_to my_passkeys_path
end
private
def set_passkey
@passkey = Current.identity.passkeys.find(params[:id])
end
end
# WebAuthn challenge endpoint (inherits from framework controller)
class My::PasskeyChallengesController < ActionPack::Passkey::ChallengesController
include Authentication
allow_unauthenticated_access
endclass Sessions::MagicLinksController < ApplicationController
allow_unauthenticated_access
def show
if magic_link = MagicLink.authenticate(params[:code])
start_new_session_for(magic_link.identity)
redirect_to session.delete(:return_to) || root_path, notice: "Signed in successfully"
else
redirect_to new_session_path, alert: "Invalid or expired link"
end
end
endclass Current < ActiveSupport::CurrentAttributes
attribute :session, :identity, :user, :account
attribute :user_agent, :ip_address
def account=(account)
super
Time.zone = account&.timezone
end
resets { Time.zone = "UTC" }
endclass MagicLinkMailer < ApplicationMailer
def sign_in_instructions(magic_link)
@magic_link = magic_link
@identity = magic_link.identity
@url = session_magic_link_url(code: magic_link.code)
mail to: @identity.email_address, subject: "Sign in to #{app_name}"
end
endclass SessionCleanupJob < ApplicationJob
def perform
Session.where("created_at < ?", 30.days.ago).delete_all
MagicLink.where("expires_at < ?", 1.day.ago).delete_all
end
end
# config/recurring.yml
# production:
# cleanup_old_sessions:
# command: "SessionCleanupJob.perform_later"
# schedule: every day at 3amclass Signup
include ActiveModel::Model
attr_accessor :email_address, :full_name, :password
validates :email_address, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }
validates :full_name, presence: true
def save
return false unless valid?
ActiveRecord::Base.transaction do
@identity = Identity.create!(email_address: email_address, password: password)
@identity.create_user!(full_name: full_name)
@identity.send_magic_link(purpose: "verify_email")
end
true
rescue ActiveRecord::RecordInvalid
false
end
def identity = @identity
end<%# app/views/sessions/new.html.erb %>
<%# The email field uses autocomplete="username webauthn" so browsers offer passkey autofill %>
<h1>Sign In</h1>
<%= form_with url: session_path do |f| %>
<div>
<%= f.label :email_address, "Email" %>
<%= f.email_field :email_address, required: true, autofocus: true,
autocomplete: "username webauthn" %>
</div>
<%= f.submit "Send magic link" %>
<% end %>
<%# Passkey sign-in button with conditional mediation (autofill UI) %>
<%= passkey_sign_in_button "Sign in with a passkey", session_passkey_path,
options: @authentication_options, mediation: "conditional", hidden: true %>
<%# Layout header %>
<% if authenticated? %>
<span>Signed in as <%= current_user.full_name %></span>
<%= button_to "Sign out", session_path, method: :delete %>
<% else %>
<%= link_to "Sign in", new_session_path %>
<% end %>The passkey_sign_in_button helper renders a <rails-passkey-sign-in-button> web component that handles the WebAuthn ceremony. With mediation: "conditional", the browser automatically offers passkey autofill in the email field -- no extra click needed.
httponly: true, same_site: :lax, secure: Rails.env.production?sign_count on each passkey authentication to detect cloned credentialsrate_limit to: 10, within: 3.minutes on create actions (sessions and passkeys)normalizes :email_address, with: -> { _1.strip.downcase }# test/test_helper.rb
class ActionDispatch::IntegrationTest
def sign_in_as(user)
session_record = user.identity.sessions.create!
cookies.signed[:session_token] = session_record.token
end
def sign_out
cookies.delete(:session_token)
end
endclass SessionsControllerTest < ActionDispatch::IntegrationTest
test "create sends magic link" do
identity = identities(:david)
assert_enqueued_emails 1 do
post session_path, params: { email_address: identity.email_address }
end
assert_redirected_to new_session_path
end
test "destroy terminates session" do
sign_in_as users(:david)
delete session_path
assert_redirected_to root_path
assert_nil cookies[:session_token]
end
endhas_secure_token, clean up old sessions, track passkey sign countsreferences/auth-components.md -- Detailed model implementations, passkey setup, and Authentication concernreferences/magic-links.md -- Magic link flow, token generation, expiry patterns© dilolabs, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 2 other files (references) in .vibe/skills/auth-setup of dilolabs/nosia.
Open the folder on GitHubat commit 0ef5e5d
We found 3 copies of this SKILL.md (exact, near-identical or edited) in other folders, from 1 other GitHub owner. This page covers the copy in dilolabs/nosia, which our catalogue first saw on October 7, 2026.
Auth Setup next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Auth Setup this skilldilolabs/nosia | 213 | 1 repos | ~2.9k | Automated safety check: Pass | MIT | |
| Authentication FlowThibautBaissac/rails_ai_agents | 665 | — | ~1.9k | Automated safety check: Pass | MIT | |
| Fortify Developmentcoollabsio/coolify | 63k | 4 repos | ~1.9k | Automated safety check: Pass | MIT | |
| Supabase Development and Debuggingsupabase/agent-skills | 2.7k | 3 repos | ~3.6k | Automated safety check: Pass | MIT | |
| Better Auth Best Practiceslatitude-dev/latitude-llm | 4.7k | 7 repos | ~1.6k | Automated safety check: Pass | MIT | |
| Supabasecurvenote/curvenote | 169 | 5 repos | ~2.2k | Automated safety check: Pass | Custom licence |
ThibautBaissac/rails_ai_agents
Implements authentication using Rails 8 built-in generator. An agent skill from ThibautBaissac/rails_ai_agents.
coollabsio/coolify
ACTIVATE when the user works on authentication in Laravel. An agent skill from coollabsio/coolify.
supabase/agent-skills
General Supabase skill for database, auth, Edge Functions, Realtime and storage work, plus client libraries, migrations, security audits, debugging and reading logs.
latitude-dev/latitude-llm
Configure Better Auth server and client, set up database adapters, manage sessions, add plugins, and handle environment variables.
curvenote/curvenote
A skill your agent uses when doing ANY task involving Supabase.
aws-samples/sample-kolya-br-proxy
A skill your agent uses when the user asks how code works, wants to understand architecture, trace execution flows, or explore unfamiliar parts of the codebase.
dilolabs/nosia
Builds REST APIs using respondto blocks with Jbuilder templates following the 37signals same-controllers-different-formats philosophy.
dilolabs/nosia
Implements HTTP caching with ETags, fragment caching, Russian doll caching, and Solid Cache configuration.
dilolabs/nosia
Creates and refactors model and controller concerns for shared behavior.
dilolabs/nosia
Builds event tracking, activity feeds, and webhook systems following 37signals patterns with a generic Event model and Eventable concern.
dilolabs/nosia
Implements shallow background jobs with later/now conventions using Solid Queue.
dilolabs/nosia
Creates minimal Action Mailer classes with bundled notification patterns following 37signals conventions.
Works with
Categories
Implements custom passwordless authentication without Devise. Auth Setup is an agent skill from dilolabs/nosia. Implements custom passwordless authentication without Devise.
Auth Setup fits situations like: setting up authentication; session management; passkeys (WebAuthn); password resets.
Run `npx skills add dilolabs/nosia --skill auth-setup -a claude-code`. Or copy the skill folder (.vibe/skills/auth-setup in dilolabs/nosia) into .claude/skills/auth-setup in your project. Claude Code loads it when a task matches its description.
Run `npx skills add dilolabs/nosia --skill auth-setup -a codex`. Or copy the skill folder (.vibe/skills/auth-setup in dilolabs/nosia) into .agents/skills/auth-setup in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add dilolabs/nosia --skill auth-setup -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/auth-setup, .gemini/skills/auth-setup, .github/skills/auth-setup and .opencode/skills/auth-setup in your project.
Going by SKILL.md and its folder, Auth Setup needs the command-line tools its instructions call (rails). Compatibility (from SKILL.md): Ruby 3.3+, Rails 8.0+.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Auth Setup is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 2.9k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 3.9k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Auth Setup: Authentication Flow (ThibautBaissac/rails_ai_agents, 665 stars), Fortify Development (coollabsio/coolify, 63k stars), Supabase Development and Debugging (supabase/agent-skills, 2.7k stars) and Better Auth Best Practices (latitude-dev/latitude-llm, 4.7k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
dilolabs (a GitHub organization) maintains it in dilolabs/nosia, which has 213 GitHub stars. The repository holds 15 skills in this directory. The repository was last updated on September 9, 2026.
Source: dilolabs/nosia on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.