Class: DoorMat::AccessToken
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- DoorMat::AccessToken
- Includes:
- AttrSymmetricStore
- Defined in:
- app/models/door_mat/access_token.rb
Instance Attribute Summary collapse
-
#is_public ⇒ Object
Returns the value of attribute is_public.
-
#remember_me ⇒ Object
Returns the value of attribute remember_me.
-
#token ⇒ Object
Returns the value of attribute token.
Class Method Summary collapse
- .clean_up(cookies) ⇒ Object
- .clear_current_access_token ⇒ Object
- .create_from_params(token_for, identifier, confirm_identifier, name, is_public, remember_me, request) ⇒ Object
- .current_access_token ⇒ Object
- .destroy_if_linked_to(cookies) ⇒ Object
- .is_cookie_present?(cookies) ⇒ Boolean
- .load_token(token, request, verbose = true) ⇒ Object
- .new_with_token_for(token_for, request) ⇒ Object
- .swap_token!(cookies, valid_current_session_tokens, new_session_token, force_new_token_generation = false) ⇒ Object
- .token_for_is_valid(token_for_symbol) ⇒ Object
- .validate_from_cookie(cookies, request) ⇒ Object
- .validate_token(token, cookies, request) ⇒ Object
Instance Method Summary collapse
- #default_failure_url ⇒ Object
- #default_parameters ⇒ Object
- #default_success_url ⇒ Object
- #form_submit_path(controller) ⇒ Object
- #generate_new_token ⇒ Object
- #generic_redirect_url ⇒ Object
- #init ⇒ Object
- #initialization_performed? ⇒ Boolean
- #load_actor_for_session ⇒ Object
- #load_sub_session ⇒ Object
- #renew_token(cookies) ⇒ Object
- #session_parameters ⇒ Object
- #set_up(cookies) ⇒ Object
Methods included from AttrSymmetricStore
Instance Attribute Details
#is_public ⇒ Object
Returns the value of attribute is_public.
14 15 16 |
# File 'app/models/door_mat/access_token.rb', line 14 def is_public @is_public end |
#remember_me ⇒ Object
Returns the value of attribute remember_me.
14 15 16 |
# File 'app/models/door_mat/access_token.rb', line 14 def remember_me @remember_me end |
#token ⇒ Object
Returns the value of attribute token.
14 15 16 |
# File 'app/models/door_mat/access_token.rb', line 14 def token @token end |
Class Method Details
.clean_up(cookies) ⇒ Object
310 311 312 |
# File 'app/models/door_mat/access_token.rb', line 310 def self.clean_up() .delete(:token) end |
.clear_current_access_token ⇒ Object
35 36 37 38 39 40 41 |
# File 'app/models/door_mat/access_token.rb', line 35 def self.clear_current_access_token access_token = current_access_token RequestStore.store[:current_access_token] = nil access_token.destroy if access_token.persisted? nil end |
.create_from_params(token_for, identifier, confirm_identifier, name, is_public, remember_me, request) ⇒ Object
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'app/models/door_mat/access_token.rb', line 59 def self.create_from_params(token_for, identifier, confirm_identifier, name, is_public, remember_me, request) clear_current_access_token is_public = '1' == is_public.to_s remember_me = '1' == remember_me.to_s access_token = new_with_token_for(token_for, request) return access_token unless access_token.errors.blank? access_token.identifier = identifier access_token.name = name || 'access token' if access_token.identifier.blank? access_token.errors[:identifier] << I18n.t("door_mat.password_less_session.blank_identifier") return access_token end if access_token.session_parameters[:challenge].include? :email if DoorMat::Regex.simple_email.match(access_token.identifier).blank? access_token.errors[:identifier] << I18n.t("door_mat.password_less_session.expect_email_identifier") return access_token end end unless identifier == confirm_identifier access_token.errors[:identifier] << I18n.t("door_mat.password_less_session.identifier_error") return access_token end unless [:single_use, :multiple_use].include? access_token.session_parameters[:status] DoorMat.configuration.logger.error "ERROR: #{request.remote_ip} Status must be either :single_use or :multiple_use check your configuration - found #{access_token.session_parameters[:status]}" access_token.errors[:base] << I18n.t("door_mat.password_less_session.create_failed") return access_token end access_token.status = access_token.session_parameters[:status] unless access_token.load_sub_session access_token.errors[:base] << I18n.t("door_mat.password_less_session.actor_missing") return access_token end access_token.generate_new_token if is_public access_token.public_computer! else access_token.private_computer! end # User asked to be remembered if DoorMat.configuration.allow_remember_me_feature && remember_me access_token.remember_me! unless ( DoorMat.configuration.remember_me_require_private_computer_confirmation && access_token.public_computer? ) end access_token end |
.current_access_token ⇒ Object
31 32 33 |
# File 'app/models/door_mat/access_token.rb', line 31 def self.current_access_token RequestStore.store[:current_access_token] ||= self.new end |
.destroy_if_linked_to(cookies) ⇒ Object
290 291 292 293 294 295 296 297 298 299 |
# File 'app/models/door_mat/access_token.rb', line 290 def self.destroy_if_linked_to() token = .encrypted[:token] || '' clean_up() access_token = load_token(token, nil, false) return false if access_token.blank? access_token.destroy! unless access_token.multiple_use? true end |
.is_cookie_present?(cookies) ⇒ Boolean
205 206 207 |
# File 'app/models/door_mat/access_token.rb', line 205 def self.() !.encrypted[:token].blank? end |
.load_token(token, request, verbose = true) ⇒ Object
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'app/models/door_mat/access_token.rb', line 209 def self.load_token(token, request, verbose=true) token = token.to_s.strip if DoorMat::Regex.session_guid.match(token).blank? DoorMat.configuration.logger.warn "WARN: #{request.remote_ip} Attempted to use token with invalid format #{token}" if verbose return nil end access_token = self.find_by_hashed_token DoorMat::Crypto::FastHash.sha256(token) if access_token.blank? DoorMat.configuration.logger.warn "WARN: #{request.remote_ip} Attempted to use inexistent token #{token}" if verbose return nil end return nil unless access_token.load_sub_session # Reload the token using find now that the sub_session is loaded # to allow the encrypted field to be decrypted # the request hits the cache so there is no additional round trip to the DB access_token = self.find(access_token.id) access_token.token = token access_token end |
.new_with_token_for(token_for, request) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 |
# File 'app/models/door_mat/access_token.rb', line 47 def self.new_with_token_for(token_for, request) access_token = self.new token_for_symbol = token_for.to_s.strip.to_sym if token_for_is_valid(token_for_symbol) access_token.token_for = self.token_fors[token_for_symbol] else DoorMat.configuration.logger.warn "WARN: #{request.remote_ip} Attempted to use inexistent token_for #{token_for}" access_token.errors[:base] << I18n.t("door_mat.password_less_session.create_failed") end access_token end |
.swap_token!(cookies, valid_current_session_tokens, new_session_token, force_new_token_generation = false) ⇒ Object
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'app/models/door_mat/access_token.rb', line 166 def self.swap_token!(, valid_current_session_tokens, new_session_token, force_new_token_generation = false) access_token = current_access_token # Our current access token is in order return unless access_token.valid? valid_transitions = access_token.session_parameters.fetch(:transitions, []) # The current access token is for one of the valid_current_session_tokens return unless Array(valid_current_session_tokens).include? access_token.token_for.to_sym # The transition is valid return unless valid_transitions.include? new_session_token blank_new_session_access_token = self.new blank_new_session_access_token.token_for = self.token_fors[new_session_token] return unless blank_new_session_access_token.load_actor_for_session issue_new_token = force_new_token_generation || access_token.multiple_use? || (access_token.actor_id != blank_new_session_access_token.actor_id) if issue_new_token RequestStore.store[:current_access_token] = blank_new_session_access_token if access_token.used? access_token.destroy! end blank_new_session_access_token.renew_token() blank_new_session_access_token.name = access_token.name blank_new_session_access_token.identifier = access_token.identifier blank_new_session_access_token.data = access_token.data blank_new_session_access_token.reference_id = access_token.reference_id blank_new_session_access_token.used! else # For a single user ticket, just update the token_for value if access_token.used? access_token.token_for = self.token_fors[new_session_token] access_token.save! end end end |
.token_for_is_valid(token_for_symbol) ⇒ Object
43 44 45 |
# File 'app/models/door_mat/access_token.rb', line 43 def self.token_for_is_valid(token_for_symbol) DoorMat.configuration.password_less_sessions.has_key? token_for_symbol end |
.validate_from_cookie(cookies, request) ⇒ Object
284 285 286 287 288 |
# File 'app/models/door_mat/access_token.rb', line 284 def self.(, request) token = .encrypted[:token] RequestStore.store[:current_access_token] = validate_token(token, , request) clean_up() if RequestStore.store[:current_access_token].nil? end |
.validate_token(token, cookies, request) ⇒ Object
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
# File 'app/models/door_mat/access_token.rb', line 238 def self.validate_token(token, , request) access_token = load_token(token, request) access_token = case when access_token.blank? nil # For an unused token, check if the link has expired against access_token.session_parameters[:expiration_delay].ago when access_token.single_use?, access_token.multiple_use? if access_token.created_at < access_token.session_parameters[:expiration_delay].ago DoorMat.configuration.logger.info "INFO: #{request.remote_ip} Attempted to use expired token #{token}" access_token.destroy! nil else access_token end # otherwise, for an ongoing session, use public / private / remember_me expiration delay when access_token.public_computer? if access_token.updated_at < DoorMat.configuration.public_computer_access_session_timeout.minutes.ago access_token.destroy! nil else access_token end when access_token.private_computer? if access_token.updated_at < DoorMat.configuration.private_computer_access_session_timeout.minutes.ago access_token.destroy! nil else access_token end when access_token.remember_me? if access_token.created_at < DoorMat.configuration.remember_me_max_day_count.days.ago access_token.destroy! nil else if access_token.updated_at < DoorMat.configuration.private_computer_access_session_timeout.minutes.ago access_token.renew_token() access_token.save end access_token end end access_token end |
Instance Method Details
#default_failure_url ⇒ Object
135 136 137 |
# File 'app/models/door_mat/access_token.rb', line 135 def default_failure_url session_parameters.fetch(:default_failure_url, generic_redirect_url) end |
#default_parameters ⇒ Object
131 132 133 |
# File 'app/models/door_mat/access_token.rb', line 131 def default_parameters @default_parameters ||= DoorMat.configuration.password_less_sessions[:password_less_defaults] end |
#default_success_url ⇒ Object
139 140 141 |
# File 'app/models/door_mat/access_token.rb', line 139 def default_success_url session_parameters.fetch(:default_success_url, generic_redirect_url) end |
#form_submit_path(controller) ⇒ Object
118 119 120 |
# File 'app/models/door_mat/access_token.rb', line 118 def form_submit_path(controller) session_parameters.fetch(:form_submit_path).inject(controller) { |lhs, rhs| lhs.send(rhs) } end |
#generate_new_token ⇒ Object
122 123 124 125 |
# File 'app/models/door_mat/access_token.rb', line 122 def generate_new_token @token = SecureRandom.uuid self.hashed_token = DoorMat::Crypto::FastHash.sha256(@token) end |
#generic_redirect_url ⇒ Object
143 144 145 |
# File 'app/models/door_mat/access_token.rb', line 143 def generic_redirect_url default_parameters.fetch(:generic_redirect_url, [:main_app, :root_url]) end |
#init ⇒ Object
18 19 20 21 |
# File 'app/models/door_mat/access_token.rb', line 18 def init self.is_public = true if self.is_public.nil? self.remember_me = false if self.remember_me.nil? end |
#initialization_performed? ⇒ Boolean
25 26 27 28 29 |
# File 'app/models/door_mat/access_token.rb', line 25 def initialization_performed? if self.actor.blank? || self.hashed_token.blank? errors.add(:base, "Access token invalid") end end |
#load_actor_for_session ⇒ Object
147 148 149 150 151 152 153 154 |
# File 'app/models/door_mat/access_token.rb', line 147 def load_actor_for_session self.actor ||= DoorMat::Actor.authenticate_with(self.session_parameters[:actor][:email], self.session_parameters[:actor][:password]) if self.actor.nil? DoorMat.configuration.logger.error "ERROR: Could not authenticate actor #{self.session_parameters[:actor][:email]} is it in your database?" return false end true end |
#load_sub_session ⇒ Object
156 157 158 159 160 161 162 163 164 |
# File 'app/models/door_mat/access_token.rb', line 156 def load_sub_session return false unless load_actor_for_session unless DoorMat::Session.current_session.session_for_actor_loaded? self.actor sub_session = DoorMat::Session.new_sub_session_for_actor(self.actor, self.session_parameters[:actor][:password]) DoorMat::Session.current_session.append_sub_session(sub_session) end true end |
#renew_token(cookies) ⇒ Object
232 233 234 235 236 |
# File 'app/models/door_mat/access_token.rb', line 232 def renew_token() generate_new_token set_up() end |
#session_parameters ⇒ Object
127 128 129 |
# File 'app/models/door_mat/access_token.rb', line 127 def session_parameters @session_params ||= DoorMat.configuration.password_less_sessions[self.token_for.to_sym] end |
#set_up(cookies) ⇒ Object
301 302 303 304 305 306 307 308 |
# File 'app/models/door_mat/access_token.rb', line 301 def set_up() = { secure: DoorMat.configuration., httponly: true } .merge!({ expires: DoorMat.configuration.remember_me_max_day_count.days.since(self.created_at) }) unless self.public_computer? .encrypted[:token] = .merge({value: self.token}) end |