Skip to content

Instantly share code, notes, and snippets.

@demelziraptor
Created May 23, 2012 23:12
Show Gist options
  • Save demelziraptor/2778430 to your computer and use it in GitHub Desktop.
Save demelziraptor/2778430 to your computer and use it in GitHub Desktop.
Devise API register and sign in using tokens
class AddDeviseColumnsToUser < ActiveRecord::Migration
def self.up
change_table :users do |t|
t.string :authentication_token
end
end
def self.down
change_table :users do |t|
t.remove :authentication_token
end
end
end
class AddUsernameToUsers < ActiveRecord::Migration
def change
add_column :users, :username, :string, :unique => true
end
end
...
devise_for :users
devise_scope :user do
resources :tokens, :only => [:create, :destroy]
end
...
class TokensController < Devise::RegistrationsController
skip_before_filter :verify_authenticity_token
respond_to :json
def create
email = params[:user]['email']
password = params[:user]['password']
username = params[:user]['username']
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
# No username, therefore login
if username.nil?
@user=User.find_by_email(email.downcase)
if @user.nil?
logger.info("User #{email} failed signin, user cannot be found.")
render :status => 401, :json => {:message => "Invalid email or passoword."}
return
end
# http://rdoc.info/github/plataformatec/devise/master/Devise/Models/TokenAuthenticatable
@user.ensure_authentication_token!
if not @user.valid_password?(password)
logger.info("User #{email} failed signin, password \"#{password}\" is invalid")
render :status=>401, :json => {:message => "Invalid email or password."}
else
render :status=>200, :json => {:token => @user.authentication_token}
end
# Username, therefore create new user
else
@useremail = User.find_by_email(email.downcase)
@username = User.find_by_username(username)
unless @useremail.nil?
render :status => 401, :json => {:message => "Email address already registered."}
return
end
unless @username.nil?
render :status => 401, :json => {:mesage => "Username already taken."}
return
end
# create new user, return token
build_resource
if resource.save
@user=User.find_by_email(email.downcase)
@user.ensure_authentication_token!
render :status => 200, :json => {:token => @user.authentication_token}
return
else
render :status => 400, :json => {:message => "New user not saved."}
return
end
end
end
def destroy
@user=User.find_by_authentication_token(params[:id])
if @user.nil?
logger.info("Token not found.")
render :status=>404, :json => {:message => "Invalid token."}
else
@user.reset_authentication_token!
render :status=>200, :json => {:token => params[:id]}
end
end
end
@demelziraptor
Copy link
Author

Based on http://matteomelani.wordpress.com/2011/10/17/authentication-for-mobile-devices/.

The migration add_devise_columns_to_user.rb is the updated version of the migration in the blog post (compatible with recent version of Devise), the other migration adds a username column to the users model. The tokens controller does sign up as well as log in - it does the sign up if you send a username parameter in the POST request. Both cases return a token. The added route gets this controller working.

The POST request should be made to http://example.com/tokens.json with the following parameters:
user[email]=[email protected]
user[password]=thepassword
user[password_confirmation]=thepassword (required for registration only)
user[username]=myusername (to register instead of log in)

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