Last active
August 29, 2015 14:05
-
-
Save tompave/4634ee65c8cea5a068fd to your computer and use it in GitHub Desktop.
Poor Man's cross-authentication
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# impersonation_utilities.rb | |
require 'digest/md5' | |
module ImpersonationUtilities | |
SHARED_SECRET = "I'm a secret string!" | |
TOKEN_VALID_FOR_DAYS = 1 | |
class << self | |
def generate_token(user_id) | |
Digest::MD5.hexdigest(SHARED_SECRET + user_id.to_s + time_dependant_salt) | |
end | |
def verify(token, user_id) | |
token == generate_token(user_id) | |
end | |
private | |
def time_dependant_salt | |
t = Time.now | |
day = (t.yday / TOKEN_VALID_FOR_DAYS.to_f).ceil | |
t.year.to_s + day.to_s | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class PseudoImpersonationRequestsController < ManagementController | |
# POST /manage/impersonation_request | |
# | |
# params: | |
# user_id | |
# | |
def impersonation_request | |
user = User.where(id: params[:user_id]).first | |
if user | |
token = ImpersonationUtilities.generate_token(user.id) | |
url = build_url(user.id, token) | |
redirect_to(url) | |
else | |
head 404 | |
end | |
end | |
private | |
def build_url(user_id, token) | |
'https://www.example.com/impersonate' + build_query_string(user_id, token) | |
end | |
def build_query_string(user_id, token) | |
"?id=#{user_id}&token=#{token}" | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class PseudoImpersonationsController < ApplicationController | |
# GET /impersonate | |
# | |
# params: | |
# token | |
# user_id | |
# | |
def impersonate | |
if params[:token] && params[:user_id] | |
if ImpersonationUtilities.verify(params[:token], params[:user_id]) | |
user = User.find(params[:user_id]) | |
sign_in(user) | |
redirect_to root_path | |
else | |
head 401 | |
end | |
else | |
head 406 | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%= link_to "login as #{@user.email}", | |
manage_impersonation_request_path(@user.id), | |
method: :post, | |
target: :blank %> |
Instead of @user.id
, it is possible to use a user-unique token or salt.
Devise, for example, uses a portion of the encripted password:
https://github.com/plataformatec/devise/blob/master/lib/devise/models/database_authenticatable.rb#L136
It's (reasonably definitely, on this planet) unique, it expires each time a user updates its password, and it is not a risk if leaked (it's a substring of a bycript-hash).
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Also look at this gist from one of Devise's leads.
Devise used to include a token authenticable module (useful for APIs), but they removed it in more recent releases.
The rationale was that each developer/app usually has very specific needs, and they didn't feel they could guarantee a secure enough, good for everyone, generic implementation.