Authentication building blocks for Crystal, tied to no web framework.
Formerly kemal-auth. The name was wrong: nothing in it ever depended on
Kemal — shard.yml never declared it, and Session exchanges HTTP::Cookie
from the standard library rather than a framework’s request context. The name
simply kept people from reaching for it elsewhere.
| Module | Description |
|---|---|
|
BCrypt password hashing and validation with CNIL-compliant rules (12+ chars, uppercase, lowercase, digit, special char) |
|
JWT token generation and verification |
|
Session management via HTTP cookies, framework-agnostic |
|
Configurable SMTP server settings |
|
Password recovery via email |
|
User management and invitations |
Add to your shard.yml:
dependencies:
authn:
github: aloli-crystal/authn
version: "~> 0.1"Then run:
shards installSMTP settings can be provided in three ways (in order of priority):
smtp = Authn::SmtpConfig.new(
host: "smtp.example.com",
port: 587,
username: "user@example.com",
password: "secret",
from_address: "noreply@example.com",
from_name: "My App",
use_starttls: true
)smtp = Authn::SmtpConfig.from_hash({
"smtp_host" => "smtp.example.com",
"smtp_port" => "587",
"smtp_username" => "user@example.com",
"smtp_password" => "secret",
"smtp_from_address" => "noreply@example.com",
"smtp_from_name" => "My App"
})| Variable | Description | Default |
|---|---|---|
|
SMTP server host |
|
|
SMTP port |
|
|
Username |
(empty) |
|
Password |
(empty) |
|
Sender address |
|
|
Sender name |
|
|
Enable TLS/SMTPS |
|
|
Enable STARTTLS |
|
require "authn"
hash = Authn::Password.hash("MyStr0ng!Pass")
Authn::Password.verify("MyStr0ng!Pass", hash) # => true
errors = Authn::Password.validate("weak")
# => ["Le mot de passe doit contenir au moins 12 caractères", ...]token = Authn::Token.generate(
secret: ENV["SESSION_SECRET"],
sub: "1",
email: "user@example.com",
role: "admin"
)
payload = Authn::Token.decode(token, ENV["SESSION_SECRET"])smtp = Authn::SmtpConfig.new(host: "smtp.example.com", ...)
result = Authn::PasswordReset.send_reset_email(
email: "user@example.com",
reset_url: "https://myapp.com/reset-password",
secret: ENV["SESSION_SECRET"],
smtp: smtp
)# Validating a user's own fields — email, name, role — is your application's
# business: it owns the wording, the languages and the list of roles.
Authn::UserManager.send_invitation_email(
email: "new@example.com", prenom: "Jane",
invitation_url: "https://myapp.com/set-password",
secret: ENV["SESSION_SECRET"], smtp: smtp
)
temp_pwd = Authn::UserManager.generate_temp_password