How to implement the authentication system using emberjs and rails3? - ruby-on-rails-3.1

I'm building a app using emberjs and active_model_serializer.
I searched a lot to find out on how to implement the authentication/authorization with emberjs and rails, but couldn't.
Has anyone done this?

I am currently working on this kind of topic: I am using Devise, and have tried two kind of solutions:
Either use navigation for auth, delegating the whole process to Devise's standard controllers & views,
Or you can wrap Devise's controllers to return JSON to a pure single
page application.
I tried both and all is working well. To inconvenient with #1 is the 'old fashioned' blink at auth navigation. Solution #2 has my preference.
Here is an example of Devise auth wrapping in JSON:
class SessionsController < Devise::SessionsController
def create
resource = warden.authenticate!(auth_options)
sign_in(resource_name, resource)
render(json: resource, status: :ok) and return
end
...
The point that is still annoying me is that I had to completely override controller method, to avoid double rendering, as Devise is not yet designed to have customizable rendering.

Related

Rails API with frontend - routing email links to backend or frontend application

I have a Rails API backend and a ReactJS frontend. My backend sends custom emails that often have confirmation-like links (like email confirmation)
Should the confirmation links point to my backend directly, or should they rather load the frontend first and then make an API call to the backend?
The two alternatives I'm thinking of are:
1 - The email confirmation link hits directly
backend.example.com/email_confirmations/:confirmation_token, which then redirects to a specific success (error) page frontend.example.com/email_confirmation/success(/failure) on my frontend.
On the backend I would only need a Metal controller with minimum modules to perform redirection to the frontend app, the controller is always responding with redirects). If further actions need to be taken from the frontend, they'll hit a different API Endpoint
2 - The email confirmation links opens up my frontend at
frontend.example.com/email_confirmations/:confirmation_token that triggers an API request to backend.example.com/email_confirmations/:confirmation_token.
Then my (Json:api) backend makes a jsonapi-compliant response with a Rails APIController.
What are you doing in practice?
I decided to opt in for the first scenario but maybe systematically calling/loading the frontend first makes more sense?
How do you wire backend/frontend in those scenarios?
I have currently implemented a very simple (Metal) Controller that would just process the incoming parameters perform redirections only to the frontend. I was hoping to define "url helpers" that would point to my frontend like so:
namespace :email_redirection do
# Controller that gets hit by email confirmation links in scenario #1
resources :confirmations
end
namespace :frontend do
frontend_root = Rails.configuration.frontend_host_with_http_and_port
scope frontend_root do
# Generation of URL Helpers for the frontend app
resources :confirmations, only: [] do
get 'successful'
get 'unsuccessful'
end
end
end
And my confirmation controller would be like
class EmailRedirection::ConfirmationsController
def index
svc = MyConfirmationService.new(token: params[:confirmation_token])
if svc.confirm
redirect_to(
frontend_successful_confirmation_url,
email: svc.confirmable.email
)
else
redirect_to(frontend_unsuccessful_confirmation_url)
end
end
end
I'm getting several error and I believe maybe the url helpers are not useable with different host/port... (or I have to pass them explicitely to each call)
How can I handle that ? And if 1. is a good choice, what would be the redirection codes you'd send on success/failure (since they can only be 3xx) ?
Both solutions involve quite some wiring between the backend/frontend and I'm not sure how to best wire things up.
Note : my models use devise but because devise isn't so great with APIs/etc. I'm using my own ConfirmationService that also handles some side-effects. I don't consider Devise to be relevant here
Creating a rails route to an external URL

Django rest framework with tailormade uploadhandler gives problems with csrf token

I have a tailormade UploadHandler (SDFUploadHandler) which I want to apply to a POST in Django REST framework (DJRF). However, doing:
request.upload_handlers.insert(0, SDFUploadHandler(request, dataset))
doesn't really work as far as I understand from https://stackoverflow.com/a/30875830/214742 because the DJRF checks the csrf token and once the read has been started it is too late to change upload handlers. I also found How do I modify the file upload handlers in a class based View with CSRF middleware? which shows a neat way to circumvent the automatic csrf token checking and then doing it manually which would mean that I could run my UploadHandler. Problem is that my App needs auditing though so I need to know which user actually made the request and since I have disabled authentication in order for this to work I no longer have request.user. Can in a simple way do the authentication manually as well after I have added my upload handler? Or can the UploadHandler be hooked in earlier somehow?
Also, it's not enough for me that a solution just works with Django standard authentication but it needs to be more general because I will be using Keycloak based authentication as well.
So, I ended up going with the approach of hooking in the UploadHandler in an earlier step. Turns out the APIView class has a method named initialize_request which i tried to overide in my subclass:
class RestDatasets(APIView):
permission_classes = (IsAuthenticated,)
parser_classes = (MultiPartParser,)
serializer_class = DatasetSerializer
def initialize_request(self, request, *args, **kwargs):
if request.method == 'POST' :
request.currentDataset = DatasetModel.objects.create()
request.upload_handlers.insert(0, SDFUploadHandler(request, request.currentDataset))
return APIView.initialize_request(self, request, *args, **kwargs)
This seems to have been early enough so nothing has tampered with the data and my upload handler is used instead.

Sails.js 0.10 and passport

I was fiddling with sails.js and passport. Seems they are mend to be used together.
I have made the user models available in de db. And I am able to use the authentication by bcryptjs. This works, but dearly want to like to automatically authenticate every call, and mostly socket.io blueprint calls.
Still, I am searching for an elegant method to enable the sails.js way of integrating passport.
There are many examples, but seem a bit out-dated, not sure.
Important is the sockets. They need to be authenticated.
For e.g. every io.socket CRUD method, would be nice.
Kind regards
I found a link (http://www.bearfruit.org/2014/07/21/tutorial-easy-authentication-for-sails-js-apps/) that's pointing me in the right direction, but still not clear how this is reflected in for instance controllers
What I am trying to manage, is to have the custom api calls authenticated before they are called (configured in routes.js or by means of blueprints).
e.g:
OrderController:
module.exports = {
placeOrder: function (req, res) {
if (true === req.isSocket) {
// Pseudo code:
if (passport.authenticated(['user','admin'])) {
Order.save();
}
// end pseudo code
}
}
}
How should/is the above method secured, and I am I able to use for instance user-roles here?
I know two good solution for you question:
sails-auth
sails-generate-auth
Both implements passport, I recommend the first one, because it creates a layer to handle all authentication difficulties in model and services

My partial wasn't loading because of CanCan authorization. How can I debug that?

I was having this problem trying to render a partial via an asynchronous request from my users views.
The problem was that CanCan was not authorizing the call, because it was inside a new action that I created on user_controller.rb. I am new to Rails and I thought that putting :edit on the ability class was enough.
I caught this error because I removed the remote: true from my link, so it can render the view via a http request. Don't as me why I did that. Begginer's luck!
My question is: how could I have debugged that error if not by luck?
You could have added test cases that accounted for the rendering of that partial, for instance (with rspec):
response.should render_template(:partial => 'partial_name')

Centralized Authorization of Controllers and Actions (ASP.NET MVC 3)

Are there any possible security issues or pitfalls to, within a custom AuthorizeAttibute (registered globally), apply authorization based on the controller type and action being called?
e.g. (not real code)
string controllerFullName=_filterContext.ActionDescriptor.ControllerDescriptor.ControllerType.FullName;
string minRequiredRole = GetControllerMinRequiredRole(controllerFullName);
if(User.MeetsRoleRequirement(minRequiredRole))
{
//give access
}
else
{
//no you're not allowed
}
The main issue is with Authorization caching - so there are a few things to know. Check out the links I've posted here:
Creating a AuthorizeAttribute - what do I need to know?
Look at the code to the existing attribute and how it handles caching to ensure you arent causing the same issue the base attribute prevents.

Resources