api_guard icon indicating copy to clipboard operation
api_guard copied to clipboard

adding the implemention of cookies only

Open hassanrbh opened this issue 3 years ago • 10 comments

… try to write tests and run them, nothing shows

hassanrbh avatar Oct 09 '22 18:10 hassanrbh

needs codeclimate to change the limit of Cognitive Complexity

hassanrbh avatar Oct 09 '22 19:10 hassanrbh

Tokens Controller

`

     def create 
      create_token_and_set_header(current_resource, resource_name)
      get_token_and_set_cookie
      access_token = get_access_token_from_headers
      remove_access_token_from_headers
      @refresh_token.destroy
      blacklist_token if ApiGuard.blacklist_token_after_refreshing
    
      render_success(data: access_token, message: I18n.t('api_guard.access_token.refreshed'))
    end
private

def get_access_token_from_headers
  response.headers['Access-Token'] if response.headers
end

def get_token_and_set_cookie
  refresh_token = response.headers['Refresh-Token']
  cookies.signed[:jti]={
    :value=>refresh_token,
    :httponly=>true
  }
  remove_keys = %w(Refresh-Token)
  response.headers.delete_if { |key| remove_keys.include?(key)}
end

def remove_access_token_from_headers
  remove_keys = %w(Access-Token Expire-At)
  response.headers.delete_if { |key| remove_keys.include?(key)}
end

def find_refresh_token
  refresh_token_from_header = cookies.signed[:jti]    
  if refresh_token_from_header
    @refresh_token = find_refresh_token_of(current_resource, refresh_token_from_header)
    return render_error(401, message: I18n.t('api_guard.refresh_token.invalid')) unless @refresh_token
  else
    render_error(401, message: I18n.t('api_guard.refresh_token.missing'))
  end
end

`

Registration Controller

def create
      init_resource(sign_up_params)
      if resource.save
        create_token_and_set_header(resource, resource_name)
        get_token_and_set_cookie
        access_token = get_access_token_from_headers
        remove_access_token_from_headers
        render_success(data: access_token,message: I18n.t('api_guard.registration.signed_up'))
      else
        render_error(422, object: resource)
      end
    end

    def destroy
      current_resource.destroy
      render_success(message: I18n.t('api_guard.registration.account_deleted'))
    end

    private

    def get_access_token_from_headers
      response.headers['access-token']
    end

    def remove_access_token_from_headers
      remove_keys = %w(Access-Token Expire-At)
      response.headers.delete_if { |key| remove_keys.include?(key)}
    end

    def get_token_and_set_cookie
      refresh_token = response.headers['Refresh-Token']
      cookies.signed[:jti]={
        :value=>refresh_token,
        :httponly=>true
      }
      remove_keys = %w(Refresh-Token)
      response.headers.delete_if { |key| remove_keys.include?(key)}
    end

Tokens Controller

def create
      create_token_and_set_header(current_resource, resource_name)
      get_token_and_set_cookie
      access_token = get_access_token_from_headers
      remove_access_token_from_headers
      @refresh_token.destroy
      blacklist_token if ApiGuard.blacklist_token_after_refreshing
    
      render_success(data: access_token, message: I18n.t('api_guard.access_token.refreshed'))
    end

    private

    def get_access_token_from_headers
      response.headers['Access-Token'] if response.headers
    end

    def get_token_and_set_cookie
      refresh_token = response.headers['Refresh-Token']
      cookies.signed[:jti]={
        :value=>refresh_token,
        :httponly=>true
      }
      remove_keys = %w(Refresh-Token)
      response.headers.delete_if { |key| remove_keys.include?(key)}
    end

    def remove_access_token_from_headers
      remove_keys = %w(Access-Token Expire-At)
      response.headers.delete_if { |key| remove_keys.include?(key)}
    end

    def find_refresh_token
      refresh_token_from_header = cookies.signed[:jti]    
      if refresh_token_from_header
        @refresh_token = find_refresh_token_of(current_resource, refresh_token_from_header)
        return render_error(401, message: I18n.t('api_guard.refresh_token.invalid')) unless @refresh_token
      else
        render_error(401, message: I18n.t('api_guard.refresh_token.missing'))
      end
    end

hassanrbh avatar Oct 09 '22 19:10 hassanrbh

Thanks for the PR. I will take a look in a week.

Gokul595 avatar Oct 17 '22 15:10 Gokul595

cool, let me know. if I did something wrong,

hassanrbh avatar Oct 19 '22 18:10 hassanrbh

Thanks for this. I am interested in seeing this feature merged.

Would it be possible, please, to add some notes about the configuration options to README.md and adding them to the initializer template in lib/generators/api_guard/initializer/templates/initializer.rb? I think they are straightforward but being able to find them without reading through the code would be helpful.

jrmhaig avatar Nov 11 '22 18:11 jrmhaig

@jrmhaig hey, sorry for not being late in my response, I am applying to some jobs this day so I am busy looking, yeah for sure, I will be free this weekend, I am gonna write some docs about, thanks

hassanrbh avatar Nov 17 '22 19:11 hassanrbh

@jrmhaig hey, sorry for not being late in my response, I am applying to some jobs this day so I am busy looking, yeah for sure, I will be free this weekend, I am gonna write some docs about, thanks

No problem. I was really just saying that this would be a great feature to have and thank you for working on it. Good luck in your job applications.

jrmhaig avatar Nov 18 '22 09:11 jrmhaig

@jrmhaig thanks dude, love to hear that

hassanrbh avatar Nov 18 '22 11:11 hassanrbh

let me give you a flow of production-ready authorization

  1. we create an access token and refresh token ( the purpose of refresh tokens is just for refreshing the access token ( so it's getting a new access token to maintain the session of the user and not having to ask the user to log in again)
  2. we pass the access token just in the response body, and refresh token in the cookies for preventing XSS attacks through any kind of vulnerabilities in our app that gonna lead that attack to us.
  3. the client (react) will accept the request, and set the cookies in the user cookies session ( refresh tokens can expire in 1 year or so, the access token is different, you need to make sure to expire the access token in 1h or 30 min ) and store that access token in a variable in react and persist that or just keep the access token in the session so you just gonna keep it in the server, not the client

and also I get what are you saying but we can refresh them both, the access token and the refresh token in the same query, an example is when we identify a 403 forbidden response we send to the backend the refresh token, we expire the access token and refresh token and get new ones

hassanrbh avatar Nov 19 '22 18:11 hassanrbh

and also the purpose of blacklisting the access token is when a user's account gets hacked and that user still has the access token we can just expire that immediately but include that in the blacklist table and also it gives us the power to keep tracking of all the sessions that the user created ( smartphone, laptop, ...)

hassanrbh avatar Nov 19 '22 18:11 hassanrbh