ReckonJwt
View SourceJWT authentication library for Reckon microservices ecosystem. Provides secure, stateless authentication across all Reckon services with a consistent, easy-to-use API.
Features
- 🔐 Secure JWT Generation - Creates signed tokens with custom claims
- 🔄 Token Refresh - Automatic token refresh with extended session support
- 🛡️ Phoenix Integration - Drop-in middleware for Phoenix applications
- 🌐 Cross-Service Auth - Consistent authentication across microservices
- 📱 Device Tracking - Built-in device fingerprinting and session management
- ⚡ High Performance - Optimized for low-latency token operations
Installation
Add reckon_jwt
to your list of dependencies in mix.exs
:
def deps do
[
{:reckon_jwt, "~> 0.1.0"}
]
end
Quick Start
1. Configuration
Add to your config/config.exs
:
config :reckon_jwt, ReckonJwt.Guardian,
issuer: "reckon_identity",
secret_key: "your-256-bit-secret-key",
ttl: {4, :hours}
2. Generate Tokens
# Generate session tokens (access + refresh)
{:ok, tokens} = ReckonJwt.generate_session_tokens(
"account_123",
"session_456",
%{type: "web", fingerprint: "abc123"}
)
# tokens = %{
# access_token: "eyJ0eXAi...",
# refresh_token: "eyJ0eXAi...",
# expires_at: 1640995200,
# token_type: "Bearer",
# account_id: "account_123",
# session_id: "session_456"
# }
3. Validate Tokens
{:ok, claims} = ReckonJwt.validate_token("eyJ0eXAi...")
# claims = %{
# account_id: "account_123",
# session_id: "session_456",
# claims: %{"sub" => "account_123", ...},
# token_type: "session",
# expires_at: 1640995200
# }
4. Phoenix Integration
# In your router.ex
pipeline :authenticated do
plug ReckonJwt.Middleware
end
pipeline :admin do
plug ReckonJwt.Middleware, required_scopes: ["admin"]
end
scope "/api", MyAppWeb do
pipe_through [:api, :authenticated]
get "/profile", ProfileController, :show
get "/dashboard", DashboardController, :index
end
5. Use in Controllers
defmodule MyAppWeb.ProfileController do
use MyAppWeb, :controller
def show(conn, _params) do
account_id = ReckonJwt.Middleware.current_account_id(conn)
claims = ReckonJwt.Middleware.jwt_claims(conn)
# Use account_id to fetch user data
render(conn, "profile.json", account_id: account_id)
end
end
API Reference
Token Generation
generate_session_tokens/3
Generates both access and refresh tokens for user sessions.
ReckonJwt.generate_session_tokens(account_id, session_id, device_info \\ %{})
generate_access_token/2
Generates a simple access token for service-to-service communication.
ReckonJwt.generate_access_token(account_id, custom_claims \\ %{})
Token Validation
validate_token/1
Validates any JWT token and extracts claims.
ReckonJwt.validate_token(token)
validate_session_token/1
Validates session-specific tokens (requires session_id in claims).
ReckonJwt.validate_session_token(token)
Token Refresh
refresh_session_tokens/1
Refreshes access token using a valid refresh token.
ReckonJwt.refresh_session_tokens(refresh_token)
Middleware Options
plug ReckonJwt.Middleware, [
required_scopes: ["read", "write"], # Required token scopes
optional: false, # Make authentication optional
token_key: "authorization", # Header key for token
account_key: :current_account_id, # Conn assign key for account
claims_key: :jwt_claims # Conn assign key for claims
]
Configuration Options
Option | Description | Default |
---|---|---|
:issuer | Token issuer identifier | "reckon_identity" |
:secret_key | JWT signing secret (required) | nil |
:ttl | Access token lifetime | {4, :hours} |
:verify_issuer | Verify token issuer | true |
:allowed_drift | Clock drift tolerance (ms) | 2000 |
Error Handling
The library provides detailed error responses:
# Token validation errors
{:error, :token_expired} # Token past expiration
{:error, :invalid_signature} # Invalid token signature
{:error, :invalid_token_format} # Malformed token
{:error, :invalid_session_token} # Missing session information
# Refresh errors
{:error, :refresh_token_expired} # Refresh token expired
{:error, :invalid_refresh_token} # Invalid refresh token
Security Features
Token Claims
Tokens include comprehensive security claims:
{
"sub": "account_123",
"iss": "reckon_identity",
"aud": "reckon_services",
"exp": 1640995200,
"iat": 1640991600,
"session_id": "session_456",
"device_fingerprint": "abc123",
"device_type": "web",
"token_type": "session"
}
Best Practices
- Secure Storage: Store tokens securely on the client side
- HTTPS Only: Always transmit tokens over encrypted connections
- Rotate Secrets: Regularly rotate JWT signing keys
- Scope Validation: Use minimal required scopes for each service
- Monitor Activity: Track token usage and authentication patterns
Multi-Service Setup
Service A (Identity Service)
# Generate tokens after authentication
{:ok, tokens} = ReckonJwt.generate_session_tokens(account_id, session_id)
# Return tokens to client
json(conn, %{data: tokens})
Service B (Portal Service)
# Validate tokens from other services
pipeline :authenticated do
plug ReckonJwt.Middleware
end
# Use in controllers
def dashboard(conn, _params) do
account_id = ReckonJwt.Middleware.current_account_id(conn)
# ... use account_id for business logic
end
Development
# Install dependencies
mix deps.get
# Run tests
mix test
# Generate documentation
mix docs
# Format code
mix format
# Type checking
mix dialyzer
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Run the test suite
- Submit a pull request
License
MIT License. See LICENSE for details.
Support
For questions and support: