How to exclude login route from authentication middleware in Silex? - silex

I made a middleware to authenticate users before every request and applied it in the beginning of the whole app.
$app->before(function($request, $app) {
Auth::authenticate($request, $app);
});
But it also applied to the login route how to fix this?
it's a Rest API.

Your middleware is being run before all routes. So, you've probably got a route like this:
$routes->match('/login', function () use ($app) {
// Login etc.
});
Or you're using, GET of POST or whatever. The middleware will always be run before a route is being run. So yes, your middleware is also applied before the login since it works for every route.
You could fix it by running the middleware after your login route like this:
$routes->match('/login', function () use ($app) {
// Login etc.
})
->after($after);
More details on this can be found here!
You could also change your middleware so that it first checks whether the user is logged in already. If so, run the authentication, if not... do nothing.
$app->before(function($request, $app) {
if user is logged in {
Auth::authenticate($request, $app);
}
});
I hope this helps you out. Don't forget to mark as completed when it does the job for you, otherwise, please leave a comment or edit your question and I'll help you out!

Related

Rails Session Timeout/Warning

I've been trying to research this all day and haven't really been able to find anything that fits my needs. We need to create a session timeout (simple) for our application, but we also need a warning message to display x minutes before the timeout of the session will occur.
I have my app set up with the activerecord_session gem and have done the necessary configuration changes. I CAN write up something like this:
before_action :determine_if_session_timed_out
in the ApplicationController. My main concern with doing it this way is db hits and the fact that it seems like there should be a rails way to do it, similar to how the above linked gem has expire_after: xx minutes, but for a warning.
My two questions are--has anyone seen any apps that:
have a built-in rails way of displaying a warning when the session is about to time out?
automatically redirect after the session times out? It looks like the page doesn't redirect with the expire_after implementation for the above gem. It stays on the same page until another action is called and then redirects.
Ajax requests in your application can be caught by this piece of code,.
$(document).ajaxError(function(e, error) { switch(error.status) {
case 401: {
// page redirect unauthorized access.
location.reload();
alert(xhr.responseText);
} }
You can have look at this approach with jquery (https://codedecoder.wordpress.com/2014/05/01/jquery-inactivity-warning-logout-timer-setinterval-clearinterval/)

How can I test Stripe.js using poltergeist and Capybara?

I've been going nuts trying to write an automated test for my user sign up page. Users will be charged a recurring subscription via Stripe. They input their basic details (email, password, etc) and their credit card details on the same form, then the following flow happens:
(On the client-side) stripe.js makes an AJAX request to Stripe's servers, which (assuming everything is valid) returns a credit card token.
My javascript fills in a hidden input in the HTML form with the credit card token, and submits the form to my Rails server.
(Now on the server-side): I validate the user's basic details. If they're invalid, return (because there's no point charging them via Stripe if e.g. their email address is invalid so they can't create an account anyway.)
If they're valid, attempt to create a Stripe::Customer object, add the right subscription and charge them using Stripe's ruby gem etc.
All of this works perfectly fine... except I can't figure out how to test it. Testing step #4 is easy enough as it takes place on the server-side so I can mock out the Stripe calls with a gem like VCR.
Step #1 is what's giving me trouble. I've tried to test this using both puffing-billy and the stripe-ruby-mock gem, but nothing works. Here's my own javascript (simplified):
var stripeResponseHandler = function (status, response) {
console.log("response handler called");
if (response.error) {
// show the errors on the form
} else {
// insert the token into the form so it gets submitted to the server
$("#credit_card_token").val(response.id);
// Now submit the form.
$form.get(0).submit();
}
}
$form.submit(function (event) {
// Disable the submit button to prevent repeated clicks
$submitBtn.prop("disabled", true);
event.preventDefault();
console.log("creating token...");
Stripe.createToken(
// Get the credit card details from the form
// and input them here.
}, stripeResponseHandler);
// Prevent the form from submitting the normal way.
return false;
});
Just to reiterate, this all works fine when I test it manually. But my automated tests fail:
Failure/Error: expect{submit_form}.to change{User.count}.by(1)
expected result to have changed by 1, but was changed by 0
When I try to use the gem puffing-billy, it seems to be caching stripe.js itself (which is loaded from Stripe's own servers at js.stripe.com, not served from my own app, as Stripe don't support this.), but the call initiated by Stripe.createToken isn't being cached. In fact, when I log into my Stripe server logs, it doesn't seem that the call is even been made (or at least Stripe isn't receiving it.)
Note those console.log statements in my JS above. When I run my test suite, the line "creating token..." gets printed, but "response handler called." doesn't. Looks like the response handler is never being called.
I've left out some details because this question is already very long, but can add more on request. What am I doing wrong here? How can I test my sign up page?
UPDATE See [my comment on this Github issue] on stripe-ruby-mock for more info on what I've tried and failed.
If I understand correctly...
Capybara won't know about your ajax requests. You should be able to stub out AJAX requests with Sinatra. Have it return a fixtures much the same as VCR.
Here's an article on it.
https://robots.thoughtbot.com/using-capybara-to-test-javascript-that-makes-http
You need to boot the Sinatra app in Capybara and then match the URLs in your ajax calls.
Something like:
class FakeContinousIntegration < Sinatra::Base
def self.boot
instance = new
Capybara::Server.new(instance).tap { |server| server.boot }
end
get '/some/ajax'
# send ajax back to capybara
end
end
When you boot the server, it will return the address and port which you can write to a config that your js can use.
#server = App.boot
Then I use the address and port to config the JS app
def write_js_config
config['api'] = "http://#{#server.host}:#{#server.port}"
config.to_json
end
In spec_helper.rb send in the config to the js so your script points to your sinatra app. Mine compiles with gulp. So I just build the config into to is before the tests run:
system('gulp build --env capybara')
I've had tests which worked on manual fail in Capybara/poltergeist due to timeout. In my case, the solution was to wait for all AJAX requests to finish. Reference
Not sure whether Stripe.js uses JQuery internally, try checking for a condition set by stripeResponseHandler.
In addition to the wait_for_ajax trick mentioned, it looks like you are calling expect before your database was updated. One way to check that would be to add a breakpoint in your code(binding.pry), and check if it is a race condition issue or not.
Also, as per Capybara's documentation, introducing an expectation of a UI change makes it 'smartly' wait for ajax calls to finish:
expect(page).not_to have_content('Enter credit card details')

Ember.js session cookie based authentication with Rails and devise

I'm looking to satisfy 3 goals with my Ember.js app authentication using rails, devise and a cookie based session.
Redirected to #/sessions/new if they're not logged in.
Always show the current user's information in the application template.
If the user is logged in and they go to #/some/route directly. The current user should be loaded on load.
I've watched these embercast videos: Client-side Authentication Part 1 & Client-side Authentication Part 2. They're a little out of date but helpful.
But still can't full solution. Anyone have full Rails 4, Devise, Emberjs 1.0.0 example?
Biggest problem is having a strategy to load the current user on page load and setting the current user when the sign in form is submitted.
Right now this is my strategy:
App.User = Em.Object.extend();
App.User.reopenClass({
current: function() {
return Ember.$.getJSON("/users/current").then(function(data) {
return data
})
}
});
App.ApplicationRoute = Ember.Route.extend({
model: function() {
return App.User.current();
}
});
App.SessionsNewController = Ember.ObjectController.extend({
actions: {
save: function(data) {
var self = this, data = this.getProperties('email', 'password');
$.post("/sessions", { session: data }).always(function(response, status, data) {
if (status == "success") {
self.transitionToRoute('index');
} else {
self.set('errorMessage', data);
}
})
},
}
});
I would not say this is not doable. But you will do lots of extra and unnecessary works to get the authentication working, which can all be done with a simple page redirect.
I've collected some opinions from Derick, the author of Backbone.Marionette. Though these are for Backbone but not Ember.js, the situation of client side authentication is same.
I find it painful and unnecessary to try and make Backbone/Marionette handle the authentication and re-loading of the authorized site stuff. Once they log in, redirect them to a different URL that the server handles, and have the server send down all the stuff that they need, as an authenticated user. https://stackoverflow.com/a/18151935
Another quote from Derick as well:
Right. And there’s a lot of cases where I just flat out say, “Do not do single-page applications,” as well. And a login screen is the biggest example of that. In all of the clients that I’ve had in the last couple of years, they’ve all asked me, “Hey, I’m having this problem. I’m trying to get my login screen to give me the current user information back from the server and redo all of this stuff on the screen without refreshing everything.” My answer every single time is, “Don’t do that." http://javascriptjabber.com/056-jsj-marionette-js-with-derick-bailey/
Also think about other cases, say Gmail. You won't get a smooth transition after click "Sign in" button on Gmail's sign in page. There will be redirect with rather big data loading as well :)
From users' perspective, they won't say Gmail is not great just because there is a redirect after signing in. After all signing/sign up is much much less frequent than daily mail operations.
So my suggestion is, reload all resources after user session changed. Let Rails and Devise do these dirty jobs in traditional fashion.

Grails Spring Security Core Plugin redirect issue

I'm using the "Spring Security Core Plugin" for Grails and am using a simple map in my Config.groovy file to restrict access based on authentication type.
For example, I want to prevent users from going to the "user/create" page because obviously you wouldn't want people to be able to create other users when they're logged in (I'm ignoring for now that managers/mods would be able to have this functionality). To accomlish this, I have
grails.plugins.springsecurity.interceptUrlMap = [
'/user/create': ['IS_AUTHENTICATED_ANONYMOUSLY']
]
The only problem is, it seems to be acting like the action:
redirect uri: SpringSecurityUtils.securityConfig.successHandler.defaultTargetUrl
I want it to redirect to the page it was previously on though.
i.e. user/list, attempt to call action create from user controller, if logged in, would reidirect back to user/list.
Any help is GREATLY appreciated.
I might be wrong, but I don't think you can do what you want using ['IS_AUTHENTICATED_ANONYMOUSLY'], it won't restrict logged in user since per documentation
The token accepts any authentication, even anonymous.
Why not just put something like
//in user controller
def create() {
if(springSecurityService.currentUser) {
//let them know they're already logged in
flash.message = message(code: 'your.....message')
redirect(action: "list")
}
//else take them to create form
...
}
Also change 'IS_AUTHENTICATED_ANONYMOUSLY' to 'permitAll'. and use the if statement.

How do I add access controls to named routes in config/routes.rb?

I use require_admin! frequently in my controllers. It works great.
Now, I want to add named route like so:
# config/routes.rb
match "poniesandrainbows" => redirect("https://poniesandrainbows.com")
# ^sadly, not really a website, btw.^
How do I restrict access to that route? Is this possible? Obviously it redirects to a public URL, but I still want to keep the route private.
You cannot restrict access from routes.
The safest way to match "poniesandrainbows" with a controller where you can use require_admin! and then redirect them to the public url.
You can try to solve the problem on the front end. Maybe only show the link to admin users.
It won't stop other users to paste the link directly to their browser url though
That kind of functionality should be encapsulated in the controller. The router handles the plumbing of passing a request to the correct controller. It is the controller's job to correctly figure out how to process the request. In this cause, the controller would use the auth service (such as require_admin!) to determine if the user is allowed to be redirected or if they are doom to another fate.
It is actually possible although as the other posters mentioned very rarely a good idea. You can read about how in this blog post: (scroll down to the routes section)
http://collectiveidea.com/blog/archives/2011/05/31/user-centric-routing-in-rails-3/

Resources