Amr Ragab
Amr Ragab

Reputation: 447

Creating authentication API on ruby on rails

I'm creating a multiplayer game based on unity engine, and i want to expose and api using Ruby on rails for the registration and authenticating users while doing usual operations like sign in/up, and my function like create room - which will be stored in db as an entry-

These simple operations i want the api to handle it, I'm not just asking about a tutorial to make authentication for user, i want someone to explain to be how my API mechanism will be, i will authenticate users based on tokens, as i guess, is that right?

If it's right, can anyone give me a simple steps to follow or a useful tutorial to my case, as I've searched a lot especially when "devise" is no longer supporting authentication, and for my little knowledge i don't think devise will help me in sign in operations as it works with the existence of a model not an api.

I hope i have made my points, waiting for your help : )

Upvotes: 2

Views: 849

Answers (2)

Leantraxxx
Leantraxxx

Reputation: 4596

You can use devise with simple_token_authentication

Steps:

  1. Install devise an create your authenticatable model with devise gem.

    rails generate devise MODEL
    
  2. Add acts_as_token_authenticatable to MODEL.

    If you want to authenticate the User (MODEL), you need to add the following code:

    /your_app/app/models/user.rb

    class User < ActiveRecord::Base
      acts_as_token_authenticatable
    
      # Note: you can include any module you want. If available,
      # token authentication will be performed before any other
      # Devise authentication method.
      #
      # Include default devise modules. Others available are:
      # :confirmable, :lockable, :timeoutable and :omniauthable
      devise :database_authenticatable, :registerable, :confirmable,
         :recoverable, :rememberable, :trackable, :validatable
    end
    
  3. Add routes and controllers

    /your_app/app/controllers/api/base_controller.rb

    class Api::BaseController < ActionController::Base
      self.responder = ApiResponder # Ignore this, just for now.
      respond_to :json
    end
    

    All your API controllers need to inherit from base controller

    /your_app/app/controllers/api/login_attempts_controller.rb

    class Api::LoginAttemptsController < Api::BaseController
      def create
        respond_with Api::LoginAttempt.new(params[:email], params[:password])
      rescue
        render nothing: true, status: 401
      end
    end
    

    /your_app/app/models/api/login_attempt.rb

    class Api::LoginAttempt
      include ActiveModel::Serializers::JSON
      attr_accessor :uid, :token
    
      def initialize(_email, _password)
        user = MobileUser.where(email: _email).first
        raise 'invalid_password' unless user.valid_password? _password
        self.uid = user.email
        self.token = user.authentication_token
      end
    
      def attributes
        { uid: nil, token: nil }
      end
    end
    

    You need the LoginAttemptsController (Call it whatever you want) to sign in the user. If the given password and email matches you will get a uid and token to authorize user's future requests.

    /your_app/app/controllers/api/bills_controller.rb

    class Api::BillsController < Api::BaseController
      acts_as_token_authentication_handler_for User
    
      def show
        respond_with bill
      end
    
      private
    
      def bill
        @bill ||= Bill.find(params[:id])
      end
    end
    

    BillsController it's just a controller to access with an authenticated request. As you can see, you need to add acts_as_token_authentication_handler_for User to protect the controller of unauthorized requests.

    /your_app/config/routes.rb

    Rails.application.routes.draw do
      namespace :api, defaults: { format: :json } do
        resources :login_attempts, only: [:create]
        resources :bills, only: [:show]
      end
    end
    

Flow:

  1. Create an User instance: User.create!(email: "[email protected]"). This will create a new user with authentication_token: "_-7CtsAxPE5SsdsfzMkY"

    You can create the user using the api. I don't do this here.

  2. Sign in performing a POST request to /api/login_attempts with the user's email and password.

    enter image description here

  3. Perform an authorized request: GET /api/bills/:id passing the headers:

    enter image description here

On this example I've used:

/your_app/app/serializers/bill_serializer.rb

class BillSerializer < ActiveModel::Serializer
  attributes :id, :created_at, :amount
end

Upvotes: 2

toddmetheny
toddmetheny

Reputation: 4443

Doorkeeper is a good alternative for api auth. Their readme is basically a tutorial for how to get set up: https://github.com/doorkeeper-gem/doorkeeper

Upvotes: 0

Related Questions