Authentication with Devise, Rails using backbone.js - ruby-on-rails

I am new to backbone and been trying to pull off an authentication but in vain. Please help over here;
My view looks like this;
mama.Views.UserSessionsIndex = Backbone.View.extend({
template: JST['user_sessions/index'],
render: function() {
this.$el.html( this.template );
return this;
},
events: {
"click #sign_in_button": "signIn"
},
signIn: function(event) {
var userSession = new Skymama.Models.UserSession;
userSession.set({email: $('#email_address').val(), password: $('#password').val()});
userSession.save({
success: function(model, response) {
alert("response");
},
error: function(model, response){
alert("response");
}
});
}
});
However, i get this response 401 Unauthorized for an authorised error. How can i handle these response, log in the client and redirect them.
Thank you

If you finally expect a redirect, don't use Backbone model because JSON response won't get you redirected.
Instead, within this Backbone view, display traditional Devise form and send HTML request.

You need a RESTful way to login from Backbone to Rails (Devise).
Tutorial 1: http://joshhuckabee.com/integrating-devise-backbonejs
Tutorial 2: http://chasseurmic.github.io/chasseurmic/blog/2013/02/13/restful-api-authentication/
Prepare the RESTful config/controller. After, using a POST call you can authenticate with Rails.

Related

Twitter authentication with Ember.js and Rails

I'm using Torii and ember-simple-auth to manage authentication on my front-side, and Knock and Omniauth-twitter on my server. I had no problem with Facebook, but Twitter using Oauth1.0, I have troubles to figure out the flow.
Here is my Torii config :
# environment.js
ENV['torii'] = {
sessionServiceName: 'sessiontorii',
providers: {
'facebook-oauth2': {
apiKey: 'API_KEY',
redirectUri: 'http://localhost:4200/'
},
'twitter': {
requestTokenUri: 'http://127.0.0.1:3000/auth/twitter'
}
}
My route or controller :
# route.js
twitterLogin() {
var self = this;
this.get('sessiontorii').open('twitter').then(function(response) {
console.log(response);
self.transitionTo('index');
}, function() {
console.log('auth failed');
});
},
A new window is opening and I can login with my Twitter account. My server does the authentication/registration, but I can't figure out how to close this new window and send the token to my front.
Is my flow completely wrong ? Or do I miss something ?
I followed this tutorial, but I wonder if it's not a bit outdated
The issue was that I was sending a wrong type of data from my server. So I updated my torii-provider and the code I was sending. Torii does the job and close the new window when it gets the data. Then, I'm sending the data to my authenticator and confirm the authentication with the JWT code.

devise not set flash messages when dealing with ajax request

When user wants to perform an action that need him to login in first, devise will redirect him to the signin page and set a flash message: 'Please signin or signup before continue'. This works well with no-ajax request. But with an ajax request that also need signin first, it will response with 401 error and we should handle it manually as follows:
$.ajax({
url: '/books/user_score',
type: 'POST',
data: { score: value, book_id: book_id },
dataType: 'json',
success: function(data) {
bookStarWidget.data('starInfo', data.book_star);
setVote(bookStarWidget);
$("[name='my_vote']").rating('disable');
},
error: function(jqXHR, textStatus, errorThrown) {
if (jqXHR.status == 401) {
window.location.assign('/users/sign_in');
}
}
});
In the above code, we manually open the signin page when received the 401 error devise sends out.
The problem is that there is NO flash message set in this way. So could someone knows how to set the flash message as usual to keep a consistent behavior?
It looks like you're using javascript to set the location in the error case. Devise has a configuration option that will redirect on failure instead of returning http headers. This setting defaults to true which forces you to handle failure on xhr manually. Here's the explanation from the source: https://github.com/plataformatec/devise/blob/master/lib/devise/failure_app.rb#L120
So, in your Devise config:
config.http_authenticatable_on_xhr = false
Try the unauthenticated ajax request again and Devise will do the redirect for you, which should set up the flash messages as you expect.

server returning 302 moved on create in Rails

I've got a Backbone.js/Rails app and I'm trying to create a new object through Backbone model.save().
The server is returning a 302 moved, but checking the rails controller, the create object exists, and I can navigate to the index, so the routes are properly in place.
I've tried replacing the backbone.js with a regular jquery .ajax function, and both return the 302, as I originally thought the error was in backbone, but I think this is showing that the error is actually in rails.
The request payload/parameters is pretty simple
{"user_id":130,"message_text":"does this go 302","authenticity_token":"GxN8nPf5YwS2j2HhWZxWiKej3Y72Vb5IQZ98u5Nl2gs="}
The backbone save method is
var user_message = new Myapp.Models.UserMessage({
user_id: user.id,
message_text: $('input[name="message"]',this.el).val()
});
user_message.save({
success: function(response) {
new Message({message: response.message});
},
error: function() {
new Error({ message: "adding message" });
}
});
A "302" response has nothing to do with backbone, as you've noted. It looks like you have authorization / authentication code that is causing this.

How use token authentication with Rails, Devise and Backbone.js?

I'm trying to build a mobile application with PhoneGap, jQuery Mobile and Backbone.js on the client-side - with a Rails 3 JSON API running server-side.
I know how to fetch the token from the server after being authenticated, but I don't know how to append the "token_auth" key/value to all the AJAX-requests Backbone.js will make to my server.
Here's my flow at the moment:
User types in some form fields and hits "Log in"
Backbone creates a new Player object with the email and password info.
I run a Player.authenticate that sets the token to AUTHENTICATION_TOKEN
All requests after this should append "auth_token=" + AUTHENTICATION_TOKEN
I've looked at http://documentcloud.github.com/backbone/#Sync for maybe overriding the AJAX calls - but that seems quite extreme for this simple task.
Does anyone have any experience with running Devise token_authentication and Backbone.js?
The key is to introduce it in the Backbone.sync method.
Take a look at this implementation: https://github.com/codebrew/backbone-rails/blob/master/vendor/assets/javascripts/backbone_rails_sync.js
You can add it yourself this way:
Backbone.old_sync = Backbone.sync
Backbone.sync = function(method, model, options) {
var new_options = _.extend({
beforeSend: function(xhr) {
var token = $('meta[name="csrf-token"]').attr('content');
if (token) xhr.setRequestHeader('X-CSRF-Token', token);
}
}, options)
return Backbone.old_sync(method, model, new_options);
};
Check out this fiddle: http://jsfiddle.net/dira/ZcY3D/14/
Why don't append it to all of your jquery ajax requests. It will add the auth_token to all of your ajax calls over jQuery. That might be useful when working directly with jQuery ajax (or libs that do so). But this might be a security issue as well (when you have ajax calls to other sites...).
// this is untested
$.ajaxSetup({ beforeSend : function(xhr, settings){
// just because the auth_token is a private information
if(!settings.crossDomain) {
// parse data object
var dataobj = JSON.parse(xhr.data);
// add authentication token to the data object
dataobj.auth_token = AUTHENTICATION_TOKEN;
// save the dataobject into the jqXHR object
xhr.data = JSON.stringify(dataobj);
}
}});
Another approach may be to write that token into the header and process it on the server side:
// thats not beautiful
$.ajaxSetup({ headers : { "auth_token" : AUTHENTICATION_TOKEN } });
Create a function like this that will send it any time an ajax request is sent to the server
$(function(){
$(document).ajaxSend(function(e, xhr, options) {
var token = $("meta[name='csrf-token']").attr("content");
xhr.setRequestHeader("X-CSRF-Token", token);
});
})

How do you pass devise authentication details to a rails controller action?

I have a controller action that is expected to be called by jquery. Here's the call:
$.ajax({
url: "/comments.json",
type: "POST",
dataType: "json",
data: {
commentable_id: $("#addCommentForm").attr("data-site-update-id"),
commentable_type: 'SiteUpdate',
content: $("#addCommentForm textarea#content").val()
},
success: function(comment) {
}
});
It works just fine, but for some reason, "current_user" is nil inside of the controller. If I force authenticate_user! as a filter, rails returns an HTTP Unauthorized.
How can I pass the authentication details so that this controller action works with devise? Even better, is there a way I can make this transparent? I don't want to pass the authentication details over and over for each ajax request...
In Java, once a user is logged in... they are logged in. You don't have pass anything from url to url anymore - it's in a session somewhere and it's all occuring transparently. Is there a way I can do this with rails? I don't want to focus on these details.
Thanks
EDIT: The solution is to add the following to your javascript somewhere:
$(document).ajaxSend(function(e, xhr, options) {
var token = $("meta[name='csrf-token']").attr("content");
xhr.setRequestHeader("X-CSRF-Token", token);
});
Devise does maintain sessions.
This may be your problem.

Resources