Class: HaveAPI::Authentication::Token::Provider
- Defined in:
- lib/haveapi/authentication/token/provider.rb
Overview
Provider for token authentication.
This provider has to be configured using Config.
Token auth contains API resource ‘token`. User can request a token by calling action `Request`. The returned token is then used for authenticating the user. Client sends the token with each request in configured Config#http_header or Config#query_parameter.
Token can be revoked by calling action ‘Revoke` and renewed with `Renew`.
Example usage:
Token model:
class ApiToken < ActiveRecord::Base
belongs_to :user
validates :user_id, :token, presence: true
validates :token, length: {is: 100}
enum lifetime: %i(fixed renewable_manual renewable_auto permanent)
def renew
self.valid_to = Time.now + interval
end
end
Authentication provider configuration:
class MyTokenAuthConfig < HaveAPI::Authentication::Token::Config
request do
handle do |req, res|
user = ::User.find_by(login: input[:user], password: input[:password])
if user.nil?
res.error = 'invalid user or password'
next res
end
token = SecureRandom.hex(50)
valid_to =
if req.input[:lifetime] == 'permanent'
nil
else
Time.now + req.input[:interval]
user.tokens << ::Token.new(
token: token,
lifetime: req.input[:lifetime],
valid_to: valid_to,
interval: req.input[:interval],
label: req.request.user_agent,
)
res.token = token
res.valid_to = valid_to
res.complete = true
res.ok
end
end
renew do
handle do |req, res|
t = ::Token.find_by(user: req.user, token: req.token)
if t && t.lifetime.start_with('renewable')
t.renew
t.save
res.valid_to = t.valid_to
res.ok
else
res.error = 'unable to renew token'
res
end
end
end
revoke do
handle do |req, res|
req.user.tokens.delete(token: req.token)
res.ok
end
end
def find_user_by_token(request, token)
t = ::Token.find_by(token: token)
if t
# Renew the token if needed
if t.lifetime == 'renewable_auto'
t.renew
t.save
end
t.user # return the user
end
end
end
Finally put the provider in the authentication chain:
api = HaveAPI.new(...)
...
api.auth_chain << HaveAPI::Authentication::Token.with_config(MyTokenAuthConfig)
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
Attributes inherited from Base
Class Method Summary collapse
-
.with_config(cfg) ⇒ Object
Configure the token provider.
Instance Method Summary collapse
-
#authenticate(request) ⇒ Object
Authenticate request.
- #describe ⇒ Object
-
#initialize(server, v, cfg) ⇒ Provider
constructor
A new instance of Provider.
- #resource_module ⇒ Object
- #setup ⇒ Object
-
#token(request) ⇒ String
Extract token from HTTP request.
Methods inherited from Base
auth_method, inherited, #register_routes
Constructor Details
#initialize(server, v, cfg) ⇒ Provider
Returns a new instance of Provider.
131 132 133 134 |
# File 'lib/haveapi/authentication/token/provider.rb', line 131 def initialize(server, v, cfg) @config = cfg.new(server, v) super(server, v) end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
129 130 131 |
# File 'lib/haveapi/authentication/token/provider.rb', line 129 def config @config end |
Class Method Details
Instance Method Details
#authenticate(request) ⇒ Object
Authenticate request
152 153 154 155 156 |
# File 'lib/haveapi/authentication/token/provider.rb', line 152 def authenticate(request) t = token(request) t && config.find_user_by_token(request, t) end |
#describe ⇒ Object
165 166 167 168 169 170 171 |
# File 'lib/haveapi/authentication/token/provider.rb', line 165 def describe { http_header: config.class.http_header, query_parameter: config.class.query_parameter, description: 'The client authenticates with credentials, usually username and password, and gets a token. From this point, the credentials can be forgotten and the token is used instead. Tokens can have different lifetimes, can be renewed and revoked. The token is passed either via HTTP header or query parameter.' } end |
#resource_module ⇒ Object
140 141 142 143 144 145 146 147 148 |
# File 'lib/haveapi/authentication/token/provider.rb', line 140 def resource_module return @module if @module provider = self @module = Module.new do const_set(:Token, provider.send(:token_resource)) end end |
#setup ⇒ Object
136 137 138 |
# File 'lib/haveapi/authentication/token/provider.rb', line 136 def setup @server.allow_header(config.class.http_header) end |
#token(request) ⇒ String
Extract token from HTTP request
161 162 163 |
# File 'lib/haveapi/authentication/token/provider.rb', line 161 def token(request) request.params[config.class.query_parameter] || request.env[header_to_env] end |