Module: Tina4::Auth
- Defined in:
- lib/tina4/auth.rb
Constant Summary collapse
- KEYS_DIR =
".keys"
Class Method Summary collapse
- .auth_handler(&block) ⇒ Object
- .bearer_auth ⇒ Object
-
.default_secure_auth ⇒ Object
Default auth handler for secured routes (POST/PUT/PATCH/DELETE) Used automatically unless auth: false is passed.
- .generate_token(payload, expires_in: 3600) ⇒ Object
- .hash_password(password) ⇒ Object
- .private_key ⇒ Object
- .public_key ⇒ Object
- .setup(root_dir = Dir.pwd) ⇒ Object
- .validate_token(token) ⇒ Object
- .verify_password(password, hash) ⇒ Object
Class Method Details
.auth_handler(&block) ⇒ Object
53 54 55 56 57 58 59 |
# File 'lib/tina4/auth.rb', line 53 def auth_handler(&block) if block_given? @custom_handler = block else @custom_handler || method(:default_auth_handler) end end |
.bearer_auth ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/tina4/auth.rb', line 61 def bearer_auth lambda do |env| auth_header = env["HTTP_AUTHORIZATION"] || "" return false unless auth_header =~ /\ABearer\s+(.+)\z/i token = Regexp.last_match(1) # API_KEY bypass — matches tina4_python behavior api_key = ENV["API_KEY"] if api_key && !api_key.empty? && token == api_key env["tina4.auth"] = { "api_key" => true } return true end result = validate_token(token) if result[:valid] env["tina4.auth"] = result[:payload] true else false end end end |
.default_secure_auth ⇒ Object
Default auth handler for secured routes (POST/PUT/PATCH/DELETE) Used automatically unless auth: false is passed
87 88 89 |
# File 'lib/tina4/auth.rb', line 87 def default_secure_auth @default_secure_auth ||= bearer_auth end |
.generate_token(payload, expires_in: 3600) ⇒ Object
18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/tina4/auth.rb', line 18 def generate_token(payload, expires_in: 3600) ensure_keys now = Time.now.to_i claims = payload.merge( "iat" => now, "exp" => now + expires_in, "nbf" => now ) require "jwt" JWT.encode(claims, private_key, "RS256") end |
.hash_password(password) ⇒ Object
41 42 43 44 |
# File 'lib/tina4/auth.rb', line 41 def hash_password(password) require "bcrypt" BCrypt::Password.create(password) end |
.private_key ⇒ Object
91 92 93 |
# File 'lib/tina4/auth.rb', line 91 def private_key @private_key ||= OpenSSL::PKey::RSA.new(File.read(private_key_path)) end |
.public_key ⇒ Object
95 96 97 |
# File 'lib/tina4/auth.rb', line 95 def public_key @public_key ||= OpenSSL::PKey::RSA.new(File.read(public_key_path)) end |
.setup(root_dir = Dir.pwd) ⇒ Object
12 13 14 15 16 |
# File 'lib/tina4/auth.rb', line 12 def setup(root_dir = Dir.pwd) @keys_dir = File.join(root_dir, KEYS_DIR) FileUtils.mkdir_p(@keys_dir) ensure_keys end |
.validate_token(token) ⇒ Object
30 31 32 33 34 35 36 37 38 39 |
# File 'lib/tina4/auth.rb', line 30 def validate_token(token) ensure_keys require "jwt" decoded = JWT.decode(token, public_key, true, algorithm: "RS256") { valid: true, payload: decoded[0] } rescue JWT::ExpiredSignature { valid: false, error: "Token expired" } rescue JWT::DecodeError => e { valid: false, error: e. } end |
.verify_password(password, hash) ⇒ Object
46 47 48 49 50 51 |
# File 'lib/tina4/auth.rb', line 46 def verify_password(password, hash) require "bcrypt" BCrypt::Password.new(hash) == password rescue BCrypt::Errors::InvalidHash false end |