I am using the facebooker authlogic plugin. I have it working pretty well now. However, any attempt to set the email address in User.before_connect(facebook_session) is causing a Apache to throw the following error:
Premature end of script headers: person_session, referer:
(person_session is my user_session).
Here is the code for before_connect:
def before_connect(facebook_session)
self.name = facebook_session.user.name
self.login=facebook_session.user.first_name
self.points=Person.default_points
Rails.logger.debug("*********email: "+facebook_session.user.email)
self.email=facebook_session.user.email
end
Note that the email address that is logged before the error occurs is valid.
My guess is that adding the '#' is causing it to fail. Another possibility is that it's trying to do some validation of the email address which causes the http error.
Any ideas would be appreciated.
Thanks.
Apparently you can also get the email from the facebook_session in your application. But you have to put the following in your application_controller to access the facebook_session (this was non-obvious and only discovered from another person's obscure post):
before_filter :set_facebook_session
helper_method :facebook_session
Related
In Devise, when confirmation instructions are resent and the email doesn't exist in the database, we get the error
Email not found
However, due to security, I want to remove this specific error.
I'm using custom controllers but the confirmation#create method is just invoking super.
Under that, I've removed the email field from the errors using
resource.errors.delete('email')
Printing out the errors (in the controller) after the fact shows nothing for email. However, when the request goes through and I print the resource.errors object in the shared errors partial, the error is still there.
Is there any way to remove this error completely? I'm assuming some other action is happening after the #create method that's injecting the error again.
Full method
def create
super
resource.errors.delete('email')
end
Confirmation of deletion:
Confirmation that error persists after redirect:
So, I'm trying to set up a React frontend and Rails backend with devise, and the Rails side is supposed to be an internal API. It's the first time I've ever done this, so I'm struggling with authentication. Specifically, in my SessionsController, I have this code:
def create
resource = User.find_for_database_authentication(email: params[:email])
return invalid_login_attempt unless resource
if resource.valid_password?(params[:password])
sign_in :user, resource
return render nothing: true
end
invalid_login_attempt
end
This always returns 401 Unauthorized. I check the result of calling valid_password? and it is always false.
However, if I replace find_for_database_authentication with find_by, the valid_password? works with no problems. Why is this? It's okay if for now the user can only enter his email and not his password, but this really confuses me. It also bugs me that this doesn't use any token checking (different issue).
On the side, I'm also wondering about whether or not CSRF tokens are okay for internal APIs (should I use a different token-auth?), and how I'm supposed to include a CSRF token with a login form if the user isn't logged in yet, but I guess those are questions for another post. Thanks for any help.
I've been following the AngularJS Tutorial for Rails on Thinkster and right now I'm nearly at the end of User Authentication with Devise. The app seems to run properly on my local server, but when I look at the console I always see the message:
Failed to load resource: the server responded with a status of 401
(Unauthorized) http://localhost:3000/users/sign_in.json
A few sections of the tutorial have been outdated and I've found answers through here and blog posts, for example there was a routing error that required bundle update which had been addressed at the question AngularJS and Rails routing error. (it won't let me post all relevant links because I am a newbie so I can't post more than 2, but there were many small things like that so far in the tutorial).
So far I can't figure out why I'm getting the 401, why it's relevant when the app is still functional, and how to fix it.
I'm not completely sure which parts of the code would be relevant. I have the whole repo on github/KellyTeresa/angular-news but will be glad to pull out and add relevant code blocks if you can point me in the right direction.
You're probably missing your CSRF token, which is accessible as the form_authenticity_token variable in Rails. You can include it in your form like so:
<input name="authenticity_token" type="hidden" ng-model="myModal.token" ng-init="myModel.token='<%= form_authenticity_token %>'">
Then ensure your model has the token attributes like so:
$scope.myModel = {
email: $scope.email,
password: $scope.password,
token: $scope.token
}
I'm seeing this along with the 401 status codes in chrome devtools E.g.:
{error: "You need to sign in or sign up before continuing."}
and
{error: "Invalid email or password."}
I think these are 401 status codes returned when Devise is checking to see if we're logged in / trying to log us in.
I'm not sure whether they have a huge negative impact when left as is (they don't seem to) what the best way to handle them is (interceptors looks possible) but these looks like starting points:
https://github.com/cloudspace/angular_devise
https://technpol.wordpress.com/2013/09/23/angularjs-and-devise-authentication-with-a-rails-server/
in your config/initializers/devise.rb ensure you have changed
#config.navigational_formats = ['*/*', :html]
to
config.navigational_formats = ['*/*', :html, :json]
I'm building a basic API where user information can be retrieved after that user's login and password are correctly sent.
Right now I'm using something like this:
http://foo:bar#example.com/api/user.xml
So, what I need to do is access the user/password sent in the request (the foo and bar) but am not sure how to access that info in a Rails controller.
Then I'd check those variables via a quick User.find and then set those as the username and password variables for authenticate_or_request_with_http_basic.
It's possible I'm looking at this at the completely wrong way, but that's where I'm at right now. :)
The answer to your question of how to get the credentials from the request is this:
user, pass = ActionController::HttpAuthentication::Basic::user_name_and_password(request)
However authenticate_or_request_with_http_basic is all you need to do basic auth:
class BlahController < ApplicationController
before_filter :authenticate
protected
def authenticate
authenticate_or_request_with_http_basic do |username, password|
# you probably want to guard against a wrong username, and encrypt the
# password but this is the idea.
User.find_by_name(username).password == password
end
end
end
authenticate_or_request_with_http_basic will return a 401 status if credentials are not supplied, which will pop up the username/password dialog in a browser. If details are given then those are passed to the block provided. If the block returns true the request goes through. Otherwise the request processing is aborted and a 403 status is returned to the client.
You can also check out Railscast 82 (thats were the code above is from):
http://railscasts.com/episodes/82-http-basic-authentication
The rails plugin Authlogic supports this functionality (as well as much more) out of the box. You could root around in the source for it, or simply integrate it into your existing application.
Edit:
After digging around the source code for Authlogic, I found this file which uses the following piece of code to grab the username and password:
def authenticate_with_http_basic(&block)
#auth = Rack::Auth::Basic::Request.new(controller.request.env)
if #auth.provided? and #auth.basic?
block.call(*#auth.credentials)
else
false
end
end
I'd look a bit further into where it all goes, but I've got to get to bed. Hope I was of some help.
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...