lib/tiny_auth.rb in tiny_auth-0.2.0 vs lib/tiny_auth.rb in tiny_auth-1.0.0
- old
+ new
@@ -1,76 +1,42 @@
+require "openssl"
+require "tiny_auth/model"
+require "tiny_auth/controller"
require "tiny_auth/version"
-require "globalid"
-require "active_record"
-require "active_support/core_ext/securerandom"
-class TinyAuth
- def initialize(model, scope: model, secret: secret_key_base)
- @model = model
- @scope = scope
- @secret = secret
+module TinyAuth
+ class << self
+ # A secret that is used for hashing tokens.
+ #
+ # If `Rails` is defined, it will attempt to use
+ # `Rails.application.secret_key_base`.
+ #
+ # @raise [RuntimeError]
+ # @return [String]
+ def secret
+ @secret || secret_key_base || missing_secret!
+ end
- raise ArgumentError, "missing argument: model" if model.nil?
- raise ArgumentError, "missing keyword: secret" if secret.nil?
- end
+ # Configure the secret that is used for hashing tokens.
+ # @param secret [String]
+ def secret=(secret)
+ @secret = secret
+ end
- def find_by_email(email)
- scope.find_by(model.arel_table[:email].lower.eq(email.downcase))
- end
+ # Create a hash from a value using the secret
+ # @param value [String]
+ # @return [String]
+ def hexdigest(value)
+ OpenSSL::HMAC.hexdigest("SHA256", secret, value)
+ end
- def find_by_credentials(email, password)
- resource = find_by_email(email)
- resource if resource&.authenticate(password)
- end
+ private
- def generate_token(resource, purpose: :access, expires_in: 24.hours)
- resource.to_sgid(expires_in: expires_in, for: purpose).to_s
- end
+ def secret_key_base
+ Rails.application.secret_key_base if defined? Rails
+ end
- def find_by_token(token, purpose: :access)
- GlobalID::Locator.locate_signed(token, for: purpose)
- rescue ActiveRecord::RecordNotFound
- end
-
- def generate_reset_token(resource, **opts)
- generate_single_use_token(resource, purpose: :reset, **opts)
- end
-
- def generate_single_use_token(resource, purpose:, expires_in: 2.hours)
- token = SecureRandom.base58(24)
-
- resource.update!(
- "#{purpose}_token" => hmac(token),
- "#{purpose}_token_expires_at" => expires_in.from_now
- )
-
- token
- end
-
- def exchange_reset_token(token, **opts, &block)
- exchange_single_use_token(token, purpose: :reset, **opts, &block)
- end
-
- def exchange_single_use_token(token, purpose:, update: {})
- not_expired = model.arel_table[:"#{purpose}_token_expires_at"].gt(Time.now)
- resource = scope.where(not_expired).find_by(:"#{purpose}_token" => hmac(token))
-
- return if resource.nil?
- yield resource if block_given?
-
- resource.assign_attributes(update)
- resource.update!("#{purpose}_token" => nil, "#{purpose}_token_expires_at" => nil)
- resource
- end
-
- private
-
- attr_reader :model, :scope, :secret
-
- def hmac(value)
- OpenSSL::HMAC.hexdigest("SHA256", secret, value)
- end
-
- def secret_key_base
- Rails.application.secret_key_base if defined?(Rails)
+ def missing_secret!
+ raise "You need to configure TinyAuth.secret"
+ end
end
end