Skip to content

artembaikuzin/redis_token

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

redis_token

API tokens redis store

Installation

Add this line to your application's Gemfile:

gem 'redis_token'

And then execute:

$ bundle

Or install it yourself as:

$ gem install redis_token

Usage

before_action :create_service

def auth
  client = Client.find_by_email(params[:email])

  if client.password == params[:password]
    token = @redis_token.create(owner: "client.#{client.id}", payload: { source: :native })
    json(access_token: token)

    # ...
  end

  # ...
end

def secured_method
  value = @redis_token.get(params[:access_token])
  return unathorized unless value

  client = Client.find_by_id(value[:owner])
  payload = value[:payload]

  # ...
end

def client_tokens
  @tokens = @redis_token.owned_by("client.#{client.id}").map do |token, value|
    { token: token, value: value }
  end
end

private

def create_service
  @redis_token ||= RedisToken.new(ttl: 30.days)
end

RedisToken creation

Implicit Redis instance creation:

# Redis.new with no arguments:
r = RedisToken.new(ttl: 30.days)

# Redis.new(host: '192.168.1.1', port: 33421)
r = RedisToken.new(host: '192.168.1.1', port: 33421)

Explicit Redis instance injection:

redis = Redis.new
r = RedisToken.new(redis, ttl: 30.days)
r = RedisToken.new(redis)

Create token

client_token = r.create(owner: "client.#{client.id}")
# => "eca431add3b1f0bbc6cfc73980b68708"

# Redefine default ttl:
user_token = r.create(owner: "u:#{current_user.id}", ttl: 15.hours)
# => "548a5d54eaf474c750bf83ed04bd242a"

# Create token with payload:
mobile_token = r.create(owner: "c.#{client.id}", payload: { source: :native })
# => "865249d6b87c4e6dd8f6b0796ace7fa0"

# Save exist token:
r.create(owner: 'api', token: SecureRandom.uuid)
# => "aed6e179-14b4-4a8c-9a1b-6b0f9150ede3"

# Token without an owner:
r.create
# => "9dfb0d52280965fe4dd95d21447941c2"

Get token

value = r.get('865249d6b87c4e6dd8f6b0796ace7fa0')
# => {:owner=>"c.555", :at=>1503327773, :payload=>{:source=>:native}}

# Each get request slides ttl by default:
r.ttl('865249d6b87c4e6dd8f6b0796ace7fa0')
# => 1209493
r.get('865249d6b87c4e6dd8f6b0796ace7fa0')
# => {:owner=>"c.555", :at=>1503327773, :payload=>{:source=>:native}}
r.ttl('865249d6b87c4e6dd8f6b0796ace7fa0')
# => 1209598

# To prevent ttl sliding set slide_expire to false:
r.get('865249d6b87c4e6dd8f6b0796ace7fa0', slide_expire: false)

# Token without an owner:
rt.get('9dfb0d52280965fe4dd95d21447941c2')
# => {:at=>1503327773}

Get all tokens owned by someone

5.times { r.create(owner: 'u.555') }

r.owned_by('u.555').each { |t, v| p "#{t}: #{v}" }
# "5e8c661c11955b062d8c512c201734dd: {:owner=>\"u.555\", :at=>1503327773}"
# "5607a698763a6164975b9ffc06528513: {:owner=>\"u.555\", :at=>1503327773}"
# "7ef74cb761c1595dd33058e78a125720: {:owner=>\"u.555\", :at=>1503327773}"
# "621d2a10c34e92d7f0b4fc3b00be62af: {:owner=>\"u.555\", :at=>1503327773}"
# "17f7cb676e67d6b53c48e51f1c1beeb1: {:owner=>\"u.555\", :at=>1503327773}"
# => nil

Deletion

Single token:

r.delete('865249d6b87c4e6dd8f6b0796ace7fa0')
# => true

All tokens of an owner:

r.delete_owned_by('client.1')
# => 8

All tokens without an owner:

r.delete_without_owner
# => 1

All tokens:

r.delete_all
# => 99

Serialization

redis_token uses native Marshal class for data serialization by default. You can override it like this:

require 'msgpack'

class MsgPackSerializer
  def pack(value)
    MessagePack.pack(value)
  end

  def unpack(value)
    MessagePack.unpack(value)
  end
end

r = RedisToken.new(serializer_class: MsgPackSerializer)
# Or
r = RedisToken.new
r.use(MsgPackSerializer)

About

API tokens redis store

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages