Skip to content

Instantly share code, notes, and snippets.

@gonzalo-bulnes
Last active August 24, 2017 09:41
Show Gist options
  • Save gonzalo-bulnes/9001010 to your computer and use it in GitHub Desktop.
Save gonzalo-bulnes/9001010 to your computer and use it in GitHub Desktop.
A SimpleTokenAuthentication-compatible JSON version of Devise::SessionsController. (UPDATE: For a discussion about this gist and a better version of it, please see https://github.com/gonzalo-bulnes/simple_token_authentication/issues/48#issuecomment-42133939)
# app/controllers/sessions_controller.rb
class SessionsController < Devise::SessionsController
# This controller provides a JSON version of the Devise::SessionsController and
# is compatible with the use of SimpleTokenAuthentication.
# See https://github.com/gonzalo-bulnes/simple_token_authentication/issues/27
def create
# Fetch params
email = params[:session][:email] if params[:session]
password = params[:session][:password] if params[:session]
id = User.find_by(email: email).try(:id) if email.presence
# Validations
if request.format != :json
render status: 406, json: { message: 'The request must be JSON.' }
return
end
if email.nil? or password.nil?
render status: 400, json: { message: 'The request MUST contain the user email and password.' }
return
end
# Authentication
user = User.find_by(email: email)
if user
if user.valid_password? password
user.reset_authentication_token!
# Note that the data which should be returned depends heavily of the API client needs.
render status: 200, json: { email: user.email, authentication_token: user.authentication_token, id: id }
else
render status: 401, json: { message: 'Invalid email or password.' }
end
else
render status: 401, json: { message: 'Invalid email or password.' }
end
end
def destroy
# Fetch params
user = User.find_by(authentication_token: params[:user_token])
if user.nil?
render status: 404, json: { message: 'Invalid token.' }
else
user.authentication_token = nil
user.save!
render status: 204, json: nil
end
end
end
@gonzalo-bulnes
Copy link
Author

Hi @kzjeef!

For some reason I didn't receive any notification and I didn't notice yours comments until now.

  1. In fact naming the action :new or :create is merely a matter of taste. I prefer to keep the API actions as similar as possible to the "not only API" ones, and that's why I use to keep using :create and to drop :new. To me, :new displays the form and, from that point of view, is useless in an API context. YMMV.
  2. and 3. Your comments make me think you found this gist without knewing about the Simple Token Authentication gem. I wrote the gist as an example of JSON-enabled Devise::SessionsController to use with Simple Token Authentication.

The gem packages the content of the gist you quoted so you don't have to worry about that. If you didn't already, I think you should take a look at it ; )

In particular this question about JSON sessions controllers contains some context for this gist.

Regards!

@dnlserrano
Copy link

Hi @gonzalo-bulnes

First of all, great work on the gem. Now the questions.

  1. I don't understand why you are using the session hash (i.e., cookies) in the create action. I'm creating a JSON API and thus the use of cookies does not seem to be the best option here.
  2. Isn't the destroy action "just another action which needs to authenticate the user"? In that sense, why do you overlook the user_email parameter in this case?

I was wondering how one could design a destroy action keeping the same ideas we are using to authenticate the user in any other action while following the DRY principles. A suggestion is to use the method for authentication in the other actions but this seems to be private to the ActsAsTokenAuthenticationHandlerMethods module.

Btw, my SessionsController is now looking like this.

Thanks in advance,
Daniel

@dnlserrano
Copy link

Hi again @gonzalo-bulnes.

After looking at this comment of yours a little more carefully, I think I got it. I now have basic custom SessionsController performing login (creation of auth_token) and logout (authenticating the user and destroying the auth_token in case authentatication was successful). Here is the new gist for it.

Would love to hear from you in regards to my previous questions anyway.

Regards!

@gonzalo-bulnes
Copy link
Author

Hi @dnlserrano, I believe you're right about both of your observations, this sessions controller needs a serious review.

I took a look to your gist; it looks better than mine. I'm aware of the Simple Token Authentication issue you opened (#48) about intenting to destroy the session with wrong credentials; once fixed, I think we could update your SessionsController and use it as a reference. Sadly I'm a bit short of time these days, but I'll be reading your updates.

@gonzalo-bulnes
Copy link
Author

Update: @dnlserrano shared his RegistrationsController and SessionsController in that gist (original comment).

@elangolab
Copy link

Hi Gonzalo (@gonzalo-bulnes),

If we are doing all the ground work, there is nothing in Devise SessionController that is required, should this class still extend Devise SessionController.

@elangolab
Copy link

@gonzalo-bulnes , btw thanks for SimpleToken

@a14m
Copy link

a14m commented Jan 6, 2015

why is this code in the gist needed... can't you just check the current_user

PS I tried to check current user but it always return a user (whether i singed in with valid or invalid token) ?

@myrual
Copy link

myrual commented Apr 26, 2017

I just write an article about how to add JSON API login based on Devise and simple token authentication. But I don't know how to test sign_out api with python code now. @gonzalo-bulnes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment