Devise Masquerade as another User
What's up guys? In this episode we're going to talk about devise masquerading and how to add this gem so that you can login as other users to make doing suppport and finding and reproducing books a little bit easier.
This is really useful in development but it can also be really useful in production if you have the need to do some support and maybe login into someone's account and try to do something and reproduce the bug or maybe just you know help them with their account so we're going to talk about the devise masquerade gem and then I'd like to do a follow-up where we talked about how this is actually implemented behind the scenes because it's actually rather interesting and not as complicated as you might think.
So this gem is a extension for devise so you're gonna have to have devise installed in order to use it. It basically just hooked in and you have a few message that you can use so you have devised master able and in your application controller you put in before filter mastery user and uh then you have your user masquerade ? methods and the ability for you to undo the masquerade afterwards so this is pretty straightforward uh if you're used to divide all these methods are kind of familiar you use similar one for current user and authenticate user and in this case we're just doing masquerading instead so what we'll need is will need some sort of the admin area in order to go use this so we'll go set that up and then we will take a look at this.
So the site I've got here is an open source project that i've got on this is really straightforward it's a link sharing app basically you drop in a link and it will part the Open Graph tags and then show up on the site and people can vote on it they're interested and one of the things that I would like to do to the admin area is to add the ability for me to login as user.
So I want to be able to click on a different user and click on a button up here to masquerade as that user so that i can log in as them test things out and development.
So with that said this will save me a lot of time in development so we can go as is this gem and and i'm going to pull the gym from the latest version on rubygems so we will have that we can then drop this and to our gem file and it go to our console and run the rails server after running bundlers, so we will now have the gem in and once that has finished and restarted the rails app.
We can go ad this
link_to into our admin views so my admin has already scoped to admins only of course and is that it's going to be important for this because you don't want average users to be able to log into someone else's account to keep that in mind make sure that if you implement this feature is either only available and development or only available for admins and it's probably good ideas to write tests for that to make sure that no not admins can access it.
So with that we can then open up our... because i'm using administrator for the admin area here we can go into a pues and I've already generated the show view and in the header action section and this is where we can add a
<%= link_to "Login As", masquerade_path(user), class: "button" %>
just like that as the masquerade path so that comes from that gem and this is going to give us the ability to masquerade so we'll add button class to that to make it look pretty and we can go back to the readme and take a look at the other changes that we need to do so for example we need to go to the user model and make it masqueradable so we'll go to the model user dot RB and oops go to user dot RB and add that here at the end
class User < ApplicationRecord devise :masqueradable ... end
And the gem also wants us to go into application controller dot RB and put in a
before_action I'm going to change this to action so we don't get the deprecated morning and we'll put in the masquerade user here
class ApplicationController < ActionController::Base ... before_action :masquerade_user! ... end
And that's going to be it so there is a couple helpers we can use to check to see if the users masquerading and to also reverse the masquerade but let's see if we get a link in the admin area and I we don't because we are using the wrong variable name here so let's fix that really quick we are looking for probably page dot resource
... <%= link_to "Login As", masquerade_path(page.resource), class: "button %> ...
because of the admin that were using that would be the user variable so we need to make sure we change that we now have the login as button so if we go open a new tab so you can see that I'm login as myself Chris and if I login is this user we are now login as test user and refreshing are other tab we see that we're logged into testuser so that means that it successfully macerated us as that user.
So what it's doing behind the scenes is actually taking the user ID that you have and you're currently logged in as and it's moving that to a different place called like masquerade user ID so it knows who is doing the masquerading so you can undo it and go back to that user account and since **it moves that and then it replaces the current user ID with the macerated users so whoever you choose the login as it makes that the current user ID and I checked for the presence of the masquerade user and that way you can add like a bar at the top saying you are login as this user, which we're going to do right now and then we can put a link in there and what it will say is it will check in both cases to see if you have a masquerade ID and your cookies and if it does then it will display that header so that you can go and remove the current user and take the masquerade user and put them back as the current user.
It's pretty straightforward was doing but they take care of everything for you I just give you a couple helpers and a couple links and voila you can build this feature in your app in like five minutes that's really cool
So what we need to do then is to go into your app/views/application.html.erb and at the top of the body we want to put in our own nav and this can be a new nav that is to contain our masqueraded user but we want to only show this nav stuff if the user is currently masquerading so let's take a look at the helpers they have a user masquerade and if we can wrap this with that if user masquerade we render this nav bar and inside of this we can have a link to undo that, so if we said paste this in
... <% if user_masquerade? %> <nav> <%= link_to "Reverse masquerade", back_masquerade_path(current_user) %> </nav> <% end %> ...
And now we have that reverse mass great link so if we save this we should get a pretty much unstyled navbar here at the top that says reverse masquerade and if we click that we go back to Chris as the user so we go back to my own account and we're automatically set up so this is really really seamless for us to be able to go do that.
Now if we go back to the admin you will notice that when we login as testuser again this time if we try to ask for the admin access we don't get any access to it there's no route that matches so we are truly login as the other user and the only way for us to know that we're logged in from a different account is they save that cookie and the session so that we know that masqueraded user, so you could use some extra stuff if you wanted to to set up the admin area so that it would use that masqueraded user account but I would really recommend that because this is going to keep that really straightforward no matter who you are logged into you can only access the things that they have permission for and that's probably the best way to go about this, so we can paste it a little bit of CSS to clean up the nav bar and make it look pretty but as far as that goes we just had to add in a link and another link with a little wrap around it to display this nav bar here and we have a fully functioning masquerading feature in our app.
And here is the style version of it so I mean a quick little change to this i added an alert style from bootstrap and change it to an alert warning and that makes it all pretty so that at the top of the page i can simply click the logout button and i am back to my current user account and anytime we see that bar above the navbar we know that we are logged in and masquerading as a different user so that's as simple as that feature is you want to see the HTML that I wrote for that i'll put that in the notes below and yeah that is all you have to do to make divise masquerade work and to follow up on this episode and then another one I would like to build this from scratch so you can see how this works behind the scenes but as you might have noticed this is a devise specific solution which works really well but what if you roll your own authentication or you're using something else like clearance how do you go about building a generic solution for this that does the same thing that just may not provide you the wonderful integration to divide as this does so we'll talk about that in another episode and follow up with this by building it from scratch till then I'll talk to you later, peace.
Credits for GoRails
This transcript was written by Victor Hazbun.