authlogic auto_register feature using my options - ruby-on-rails

I have auto registration working with authlogic using gaizka's version of authlogic_openid which I found on Github since pelle's original addition of the feature seemed to cause issues.
http://github.com/gaizka/authlogic_openid
using authlogic to auto create users bypassing explicit user registeration
This one works fine however when using the auto_register feature it ignores my options for authlogic such as retrieving the email from the openid provider... any ideas what I'm doing wrong?
Hhere's the example:
http://big-glow-mama.heroku.com/
http://github.com/holden/authlogic_openid_selector_example/tree/with-facebook/
You can see the difference if you register vs. login...
#user.rb
class User < ActiveRecord::Base
acts_as_authentic do |c|
c.validate_login_field = false
# optional, but if a user registers by openid, he should at least share his email-address with the app
c.validate_email_field = false
# fetch email by ax
c.openid_required_fields = [:email,"http://axschema.org/contact/email"]
#c.required_fields = ["http://axschema.org/contact/email"]
# fetch email by sreg
#c.optional_fields = ["email"]
end
#private method to deal with emails goes here
end
#UserSession.rb
class UserSession < Authlogic::Session::Base
auto_register
logout_on_timeout true
end

This one works fine however when using the auto_register feature it ignores my options for authlogic such as retrieving the email from the openid provider... any ideas what I'm doing wrong?
The code that handles auto-registration lives in the authlogic_openid's Session module. The code that handles registration (retrieving email form provider, etc), lives in ActsAsAuthentic module.
The first is handling a UserSession object, the latter is handling a User object.
I'll take a look in a couple of days, to see what can be done to merge both behaviours.

Solved! Thanks to this commit:
http://github.com/mreinsch/authlogic_openid/commit/4a1f644be36aec75ae2d35121904b5a846354233
by mreinsch.
Check out the example app here: http://github.com/shripadk/authlogic_openid_selector_example
Live example: http://testingauth.heroku.com/

Related

Locking a user using a per-user `maximum_attempts` value with Devise for Rails

As a de-facto standard, we all using Devise for login in our Rails application and will use the Lockable module to lock users after a particular number of failed attempts.
From Devise’s source code and the configuration option config.maximum_attempts = 20, I came to understand how Devise performs locking when the user tries to give wrong login credentials. Configuration is statically defined at Rails application boot time in initializers.
My expectation is to set the maximum_attempts dynamically – is this possible? If so, please guide me.
I have a superadmin and user below each admin. Based on the super admin I would like to set a different failed_attempt value for each user during runtime.
One possible way is to monkey-patch the Devise code that you linked to, where attempts_exceeded? is defined. Here’s a guess at what needs to be overridden:
module Devise::Models::Lockable
# assumes that the User model has a `superadmin` relation
# that has a `maximum_attempts` attribute
def attempts_exceeded?
self.failed_attempts >= self.superadmin.maximum_attempts
end
def last_attempt?
self.failed_attempts == self.superadmin.maximum_attempts - 1
end
end
This should work, but it would mean that whenever you update Devise, there is a risk of related code breaking, with unknown consequences. So you would have to review the changes to Devise before every update. And if you are discouraged from updating Devise because of this, that may eventually cause security problems if you are too slow to update to a version of Devise with a fixed security problem. So beware of those possible problems.
A safer way that requires more work up-front is to lock the user manually from your own code. The documentation for Devise::Models::Lockable mentions a public method lock_access! that locks the user when you call it. You can set the global config.maximum_attempts to some really high value such as 25. Then, in some callback on the model (I’m not sure which callback), call a method lock_access_based_on_superadmin_limit! that calls lock_access! if necessary according to your custom rules. The following definition is adapted from part of Devise’s valid_for_authentication?:
class User
# …
def lock_access_based_on_superadmin_limit!
if failed_attempts >= superadmin.maximum_attempts
lock_access! unless access_locked?
end
end
end

Using Devise to auto login a user on a multi tenancy site with subdomains

In my app a customer registers on mysite.com. Once registration is complete, they are given a site such as customer.mysite.com. I'm using Devise and would like to log the customer into their site immediately. I'm using multitenancy as explained in the RailsCast here. I'm not quite sure how to go about this. The standard solution of adding sign_in to an after_sign_up_path_for def isn't working. I'm assuming it's trying to log the customer into mysite.com, not customer.mysite.com. I'm including my after_sign_up_path_for def so you can see what I'm trying with no success. The resource in my Devise implementation is User and a user has a Site.
RegistrationsController:
def after_sign_up_path_for(resource)
# Site.current_id = resource.site.id
sign_in resource, bypass: true
"http://#{resource.site.host}.#{ENV['BASE_HOST']}/sites/#{resource.site.id}/edit"
# edit_site_url
end
Any help is appreciated.
I had the same issue and solved it the following way:
Create a new model (I called it LoginKey) that contains the user_id and a random SHA1 key.
When the user is authenticated at the parent domain (for example: mydomain.com/users/sign_in), a new LoginKey is created and the user is redirected to the corresponding subdomain to an action that I called login_with_key (for example: user_subdomain.mydomain.com/users/login_with_key?key=f6bb001ca50709efb22ba9b897d928086cb5d755322a3278f69be4d4daf54bbb)
Automatically log the user in with the key provided:
key = LoginKey.find_by_login_key(params[:key])
sign_in(key.user) unless key.nil?
Destroy the key:
key.destroy
I didn't like this solution 100%, I tried out a lot of different approaches that do not require a db record to be created, but always faced security concerns, and I think this one is safe.

Override authlogic's email validation

I am making a login using AuthLogic, but I would like 'email' to be optional. It seems however that authlogic out of the box makes this validated for. Anyone know a workaround?
from the authlogic example rails application:
Set up your model
Make sure you have a model that you
will be authenticating with. Since we
are using the User model it should
look something like:
class User < ActiveRecord::Base
acts_as_authentic do |c|
c.my_config_option = my_value # for available options see documentation in: Authlogic::ActsAsAuthentic
end # block optional
end
One thing to note here is that this tries
to take care of all the authentication
grunt work, including validating your
login, email, password, and token
fields. You can easily disable this
with configuration. Ex:
c.validate_email_field = false. See
the Authlogic::ActsAsAuthentic sub
modules in the documentation for more
details.
Key part to note:
You can easily disable this with configuration. Ex:
c.validate_email_field = false.
Hope that helps.
Source: https://github.com/binarylogic/authlogic_example
While searching my contents ..i found out
http://rdoc.info/github/binarylogic/authlogic/master/Authlogic/ActsAsAuthentic/Email/Config#merge_validates_format_of_email_field_options-instance_method
this will surely help..

Authlogic-oid with ONLY OpenID

I am implementing an internal site, for which I want our company's OpenID server to be the only means of registering and logging in. To be more specific, I don't even want a normal email and password/salt to be stored for the users in this site.
I am using authlogic with the authlogic-oid plugin, but I am getting these errors whenever I try to make a new user:
undefined local variable or method `crypted_password_field' for #<User:0xb68b7c00>
I take this to mean that authlogic is trying to generate a password for this user even though there are no password fields in my database. Is there a workaround for this, or config options I can pass to acts_as_authentic to make this work?
Figured it out. In your User model, you must specify this config in the acts_as_authentic block:
class User < ActiveRecord::Base
acts_as_authentic do |c|
c.crypted_password_field = false
end
end
Looks like maybe you're trying access the crypted_password_field property somehow. If you look at the Authlogic example the documentation lists the optional fields (#3). I was able to get Authlogic and RPX up and running without password fields so I know it's possible.

Ruby-OpenID: Requiring email-address from OpenID provider

I'm playing with the authlogic-example-app and I'm failing to get the email address from the OpenID provider (in my case: Google and Yahoo) when I register a user, resp. I get an empty response instead of an email address (check the comments in code below).
This is how my user model looks like (everything else looks like the "with_openid"-branch of the authlogic-example-app mentioned above). Besides the missing 'email', the openid-authentication-process works as expected:
class User < ActiveRecord::Base
acts_as_authentic do |c|
# not needed because I use OpenID
c.validate_login_field = false
# avoid failed validation before OpenID request
c.validate_email_field = false
# this one sets 'openid.sreg.required=email'
c.required_fields = [:email]
end
private
# overwriting the existing method in '/lib/authlogic_openid/acts_as_authentic.rb'
def map_openid_registration(registration)
# this is my problem: 'registration' is an empty hash
self.email ||= registration[:email] if respond_to?(:email) && !registration[:email].blank?
end
end
Any idea how to solve this? Has anyone here done this before using authlogic? Or even better: Do you have a working example?
Update: I checked the Google Account Authentication API and compared the request submitted by authlogic (using ruby-openid-gem and openid-authentication-plugin) with the example requests on the Google Account Authentication API docs:
Example request to authenticate and fetch email address by Google:
https://www.google.com/accounts/o8/ud
?openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0
&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select
&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select
&openid.return_to=http%3A%2F%2Fwww.example.com%2Fcheckauth
&openid.realm=http%3A%2F%2Fwww.example.com%2F
&openid.assoc_handle=ABSmpf6DNMw
&openid.mode=checkid_setup
&openid.ns.ext1=http%3A%2F%2Fopenid.net%2Fsrv%2Fax%2F1.0
&openid.ext1.mode=fetch_request
&openid.ext1.type.email=http%3A%2F%2Faxschema.org%2Fcontact%2Femail
&openid.ext1.required=email
Request submitted by my appliation:
https://www.google.com/accounts/o8/ud
?openid.assoc_handle=AOQobUcdICerEyK6SXJfukaz8ygXiBqF_gKXv68OBtPXmeafBSdZ6576
&openid.ax.mode=fetch_request
&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select
&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select
&openid.mode=checkid_setup
&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0
&openid.ns.ax=http%3A%2F%2Fopenid.net%2Fsrv%2Fax%2F1.0
&openid.ns.sreg=http%3A%2F%2Fopenid.net%2Fextensions%2Fsreg%2F1.1
&openid.realm=http%3A%2F%2Flocalhost%3A3000%2F
&openid.return_to=http%3A%2F%2Flocalhost%3A3000%2Faccount%3Ffor_model%3D1%26_method%3Dpost%26open_id_complete%3D1
&openid.sreg.required=email
While debugging the whole setup, I've found out that the openid-authentication-plugin never receives an email in the response it receives from the openid provider, this at least explains why the registration hash in my user-model is empty...
UPDATE: If you're playing around with authlogic and openid, don't forget to check out the latest railscast on this subject!
As nobody could help me, I helped myself. :-)
The short answer to my question is:
c.required_fields = [:email,"http://axschema.org/contact/email"]
Using this line, the application requests the email-address using sreg and ax (request-type supported by Google).
You can find a more detailed answer and a working implementation of authlogic-openid with the Javascript OpenID-Selector right here:
http://github.com/vazqujav/authlogic_openid_selector_example/
While this pointed me in the right direction, what I needed was:
c.openid_required_fields = [:email,"http://axschema.org/contact/email"]
This pulled in the email and set it.
# fetch email by ax
c.openid_required_fields = [
"http://axschema.org/contact/email",
"http://axschema.org/namePerson/first",
"http://axschema.org/namePerson/last",
"http://axschema.org/contact/country/home",
"http://axschema.org/pref/language"
]
This fetches in multiple values as specified # http://code.google.com/apis/accounts/docs/OpenID.html#Parameters
Though I'm still unable to fetch in the country name... name, email, language works perfectly!
Test against an OpenID server you control, since it'll let you debug every part of the OpenID sequence. There are no guarantees that Google's OpenID provider is doing the right thing. Try checking against Verisign's server, since I'm pretty sure that one at least should do the right thing with the openid.sreg.required=email field.
Your code snippet looks right to me.
the thing is i am able to fetch the parameters from the provider but am not able to extract them from the response...
i have used OpenID::AX::FetchResponse.from_success_response(open_id_response)
as the object to hold the response... what method do i use to extract email,nickname,country,etc...

Resources