This project shows how you can implement Impersonation aka "Login as x user" feature with Rails as an API.
You can view all changes required to implement Impersonation in the PR Impersonate User
I have made use of pretender gem and extended it's functionality for this implementation.
- Ruby 3.3.0
- Rails 7.2.1
- Devise 4.9.4 & Devise JWT 0.11.0
- Pretender 0.5.0
-
Clone the repo locally:
git clone git@github.com:coolprobn/impersonate-user-rails-api.git cd impersonate-user-rails-api git checkout impersonate-user
-
Setup the application with gems and database records
bin/setup
This will setup the database and also create records from the
db/seed.rb
file required to get you up and running with the project so you can test out the feature with ease. -
Start the application
bin/rails s
API will be running at http://localhost:3000
and you can use Postman or any other API client to test out the API
Please note that IDs I am using to make API calls might vary with your app, just check the database and update it to what you have if that happens.
And all of the requests we make with the API will require Authorization header with the token apart from the Login API so make sure to check you are passing Bearer token to the request if you get Unauthorized or Forbidden errors from the API.
Send POST request to http://localhost:3000/login
with the following form body:
{
"user": {
"email": "john@email.com",
"password": "john@1234"
}
}
This will log you in as an user with the admin role which is required for impersonating other users. If you are curious, you can refer to the seed file to see what other users and other records have been created in the database.
You should receive "authorization" header back when login is successful which includes the Bearer token similar to Bearer eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI ... ... ....
. You should use that token to authenticate the user going forward so save that token somewhere to reuse later.
Send POST request to http://localhost:3000/users/3/impersonate
and set the "Authorization" header for the request with the token you had got while logging in.
You will receive a response like the following on success:
{
"impersonating_user_id": 3,
"email": "john@email.com",
"id": 1,
"created_at": "2024-03-16T12:19:24.927Z",
"updated_at": "2024-09-23T16:05:05.438Z",
"name": "John",
"role": "admin",
"jti": "07000081-3be0-4280-bdde-7672e1ba4475"
}
Send POST request to http://localhost:3000/users/stop_impersonating
to stop the impersonation for the current impersonated user i.e. user with ID 3 in the example.
impersonating_user_id will come back null if API succeeds indicating logged in user is not impersonating anyone anymore.
Send DELETE request to http://localhost:3000/logout
for logging out the current user. Don't forget to send the Authorization header with token while doing so.
To test out if the impersonation feature is working correctly, you can do the following:
- Login as user with audience role
- Try to access Movie Reviews of a different user and get Forbidden error
- Login with user with admin role
- Impersonate the user for whom you were getting Forbidden error when accessing movie reviews
- Access Movie Reviews of the same user for which you had got Forbidden error before. API should respond with success status if impersonation is working correctly.
Send POST request to http://localhost:3000/login
with the following form body:
{
"user": {
"email": "mara@email.com",
"password": "mara@1234"
}
}
Send PATCH request to http://localhost:3000/movie_user_reviews/2
with the following body:
{
"movie_user_review": {
"rating": 10.0,
"review": "Titanic is a very good movie. Must watch for everyone!"
}
}
You will get Forbidden error from the API.
Send POST request to http://localhost:3000/login
with the following form body:
{
"user": {
"email": "john@email.com",
"password": "john@1234"
}
}
Note: Don't forget to copy Bearer token and update it in upcoming requests.
Send POST request to http://localhost:3000/users/3/impersonate
. You should receive a response back with Pascal's user id inside the attribute impersonating_user_id
Send PATCH request to http://localhost:3000/movie_user_reviews/2
with the following body:
{
"movie_user_review": {
"rating": 10.0,
"review": "Titanic is a very good movie. Must watch for everyone!"
}
}
You should get success response with the updated detail for the movie review now. And this also indicates impersonation feature is working correctly.
If you run into any issues while running or implementing the Impersonation user while following this project, you can create a new issue or just send me a DM on Twitter and I will try to help you out.