I have a Rails 3 app with Omniauth and Devise. I haven't been able to find a solid tutorial showing how I should write specs for testing the functionality.
What I want to achieve is to ensure that the Sign Up and Sign In forms are working... meaning users can create accounts. I also want to be sure that the Omniauth FB Connect works as well at all times.
What/how can I write test for these scenarios above?
Thanks
The tests were very useful to test the pretty complex method I have to process authentication from Yahoo, Facebook, Google and AOL. Especially the edge cases.
This should get you started, it is the first of my 10+ scenarios.
.feature file
Feature: Signinin with third party service: Google, Aol, Facebook and Yahoo
In order to use the site
As a User
I want to sign in using my Facebook or Gmail accounts
Before do
OmniAuth.config.test_mode = true
end
After do
OmniAuth.config.test_mode = false
end
Scenario Outline: Sign with valid names and emails
Given that I have a valid "<provider>" account with email "<email>" and name "<name>"
And that I am not signed in
And I go to the sign in page
When I follow image link "<provider>"
Then I should see "You signed in using your <provider> account ("
And I should see "Welcome to Death Star"
Examples: valid name and email variations
| provider | email | name |
| Google | lukeskywaler#gmail.com | luke skywlaker |
| Facebook | darth.vader#aol.com | darth vader |
my_step.rb helper:
Given /^that I have a valid "([^"]*)" account with email "([^"]*)" and name "([^"]*)"$/ do |provider, email, name|
OmniAuth.config.test_mode = true
if provider.downcase == "yahoo" or provider.downcase == "google" or provider.downcase == "aol"
# the symbol passed to mock_auth is the same as the name of the provider set up in the initializer
OmniAuth.config.mock_auth[:open_id] =
{
'provider' => "#{provider}",
'uid' => "#{provider}.com",
'user_info' => { 'email' => "#{email}", 'name' => "#{name}"}
}
else
# the symbol passed to mock_auth is the same as the name of the provider set up in the initializer
OmniAuth.config.mock_auth[:facebook] = {
'provider' => 'facebook',
'uid' => "531564247",
'credentials' => {
'token'=> "18915faketoken22|2.NKt21XnznTNEDTTERDGYXI2UUw__.3600.1302234329200-531564247|Mi0DhWREl6g-T9bMZnL82u7s4MI"
},
'user_info' => {
'nickname' => "profile.php?id=53232564247",
'email' => "#{email}",
'first_name' => "Luke",
'last_name' => "Skywalker",
'name' => "Luke Skywalker",
'image' => "http://graph.facebook.com/5asd54247/picture?type=square",
'urls' => {
'facebook' => "http://www.facebook.com/profile.php?id=5asd54247",
'website' => ""
}
},
'extra' => {
'user_hash' => {
'id' => "5asd54247",
'name' => "#{name}",
'first_name' => "#{name.split(' ')[0]}",
'last_name' => "#{name.split(' ')[1]}",
'link' => "http://www.facebook.com/profile.php?id=5asd54247",
'birthday' => "12/7/1932",
'hometown' => {
'id' => "104048449631599",
'name' => "Menlo Park, California"
},
'location' => {
'id' => "104048449631599",
'name' => "Menlo Park, California"
},
'gender' => "male",
'email' => "#{email}",
'timezone' => "-7",
'locale' => "en_US",
'verified' => true
}
}
}
end
end
Hope this help.
Related
I'm working with devise and omniauth-saml, following the instructions from https://github.com/PracticallyGreen/omniauth-saml and the omniauth Facebook example https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
I have a simplesamlphp server running, using the metadata provided by omniauth, and everything seems to be connecting properly, but the response from the simplesaml server has nil values for email, first_name, last_name and name. The weird thing is that it is returning the email and name values, just not in a useful part of the response (see below - super#man.com is the email, Clark Kent is the name)
The weird thing is that I get these nil values with both omniauth-saml and devise-saml-authenticatable gems, but I think my simplesamlphp server is configured properly.
The response from omniauth looks like this:
#<OmniAuth::AuthHash credentials=#<OmniAuth::AuthHash> extra=#<OmniAuth::AuthHash raw_info=#<OneLogin::RubySaml::Attributes:0x007fc695850148 #attributes={"urn:oid:0.9.2342.19200300.100.1.1"=>["super#man.com"], "urn:oid:2.16.840.1.113730.3.1.241"=>["Clark Kent"], "fingerprint"=>"FINGERPRINT REMOVED"}>> info=#<OmniAuth::AuthHash::InfoHash email=nil first_name=nil last_name=nil name=nil> provider="saml" uid="_ca76f49ccb6ccce7827111ae1ff0563f534f0a4d1a">
The simplesamlphp config looks like this:
$metadata['http://localhost:3000/saml/users/auth/saml/metadata'] = array(
'AssertionConsumerService' => 'http://localhost:3000/saml/users/auth/saml/callback',
'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:email',
'simplesaml.nameidattribute' => 'email',
);
I am sure that there are good values for the user in the database, and when I test authentication on the IDP itself, everything works as expected.
I solved this. The problem was that I was trying to use values that didn't use the ldap attribute names.
I changed my sp metadata as follows (after modifying my model to use first_name and last_name instead of just name)
$metadata['http://localhost:3000/saml/users/auth/saml/metadata'] = array(
'AssertionConsumerService' => 'http://localhost:3000/saml/users/auth/saml/callback',
'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:email',
'authproc' => array(
95 => array(
'class' => 'core:AttributeMap',
'givenName' => 'first_name',
'sn' => 'last_name',
'mail' => 'email',
),
96 => array(
'class' => 'core:AttributeLimit',
'email', 'first_name', 'last_name'
),
),
'simplesaml.nameidattribute' => 'email',
);
I am working on a rails app where I need to access users Google Double Click for Publisher Data. I am using the 'google-dfp-api' gem. I have set up OmniAuth for users to authenticate their DFP accounts and am storing the refresh token per the google documentation (https://developers.google.com/doubleclick-publishers/docs/authentication). I can not figure out how to use the refresh token to access the DFP api.
I am attempting to make the connection as shown below:
dfp = DfpApi::Api.new({
:authentication => {
:method => 'OAuth2',
:oauth2_client_id => GOOGLE_CLIENT_ID,
:oauth2_client_secret => GOOGLE_CLIENT_SECRET,
:user_agent => USER_AGENT,
:application_name => APP_NAME,
:oauth2_token => {
:refresh_token => GOOGLE_DFP_REFRESH_TOKEN
}
},
:service => {
:environment => 'PRODUCTION'
}
})
AnyTime I attempt to make a query after this I get the following error:
DfpApi::V201411::UserService::ApiException: [AuthenticationError.AUTHENTICATION_FAILED # ]
You do not use the refresh token to access the api, use your access_token. I am refreshing the access_token before I make a call.
Refresh your token:
def refresh_access_token
refresh_token = self.refresh_token
google_refresh_url = "https://accounts.google.com/o/oauth2/token"
response = RestClient.post google_refresh_url, :grant_type => 'refresh_token', :refresh_token => refresh_token, :client_id => ENV['GOOGLE_CLIENT_ID'], :client_secret => ENV['GOOGLE_CLIENT_SECRET']
response_hashed = JSON.parse(response)
new_access_token = response_hashed['access_token']
self.save_new_access_token(new_access_token)
end
Then the OAuth DFP API hash should look as below:
#api = DfpApi::Api.new({
:authentication => {
:method => 'OAuth2',
:oauth2_client_id => ENV['GOOGLE_CLIENT_ID'],
:oauth2_client_secret => ENV['GOOGLE_CLIENT_SECRET'],
:application_name => ENV['GOOGLE_APP_NAME'],
:client_customer_id => google_dfp_credential.google_client_customer_id,
:network_code => google_dfp_credential.network_code,
:user_agent => ENV['GOOGLE_DFP_USER_AGENT'],
:oauth2_token => {
:access_token => google_dfp_credential.access_token,
},
},
:service => {
:environment => 'PRODUCTION'
}
})
The user_agent is a unique string to your app, that should be the same every time you access the api. See the link below for more info on that:
http://googleadsdeveloper.blogspot.com/2013/11/please-set-user-agent-or-application.html
You will also need to get the network_code from the the dfp account you are accessing by logging into the dfp account manually. To my knowledge this is not returned with OAuth authentication. See step 2 in the link below for more info on how to get the network_code:
https://developers.google.com/doubleclick-publishers/docs/start
I'm having some real difficultly trying to send multiple email addresses in json to the sendgrid API.
Here is my code that works for one email address:
#result = HTTParty.post("https://api.sendgrid.com/api/newsletter/lists/email/add.json",
:body => { :list => "#{#survey.name}_#{#survey.id}", :data => '{ "name": "John Smith", "email": "john#smith.com" }', :api_user => 'XXXXX', :api_key => 'XXXXX'})
But in ruby using the :data post attribute how can I add another email address?
The following don't work - life would be too easy lol
:data => '[{"email" => "nick#sendgrid.com"},{"email" => "jane#example.com"}]'
OR
:data => '{[{"email" => "nick#sendgrid.com"},{"email" => "jane#example.com"}]}'
Apparently SendGrid expects the following....
data[]={"email" => "nick#sendgrid.com"}&data[]={"email" => "jane#example.com"}
How I can create a post parameter in rails that does this?!?
You could create your :data param as an array of JSONs, like so:
:data => ['{ "name" : "Foo Bar", "email" : "foo#bar.com" }','{ "name" : "Jon Snow", "email" : "jon#snow.com" }']
The app I am writing has the ability to have a login popup appear and it authenticates against a hard coded username/password constant pair. I would like to authenticate against our central LDAP server. the we dont have a base however we do have a bind_dn string of "cn=USERFOO,ou=it,o=corporate". The variables user/pass are passed in through the basic login box.
I am trying to do this through ActiveLdap however I dont mind using any other library as long as I can validate the credentials through a single sign on against our LDAP server using the HTTPAuth since is written completely in Webrick Ruby. Below is a sample of the function I am calling.
Does anyone have any idea how to do this?
Thanks in advance.
def authenticate_ldap(req,res)
authlabel = "LDAP Authentication"
HTTPAuth.basic_auth(req, res, authlabel) { |user, pass|
ActiveLdap::Base.setup_connection(
:host => 'ldap.internalserver.com',
:port => 389,
:bind_dn => "cn=#{user},ou=it,o=corporate",
:password_block => Proc.new { pass },
)
}
return
end
I figured out a solution. The person who manages our LDAP server provided the incorrect ldap connection string, but even with that it still didn't work.
The solution I discovered that did indeed make a connection with very basic validation is something to this effect for anyone else interested in a very simple ldap authentication popup in pure Ruby.
def authenticate(req,res)
authlabel = 'LDAP Authentication'
HTTPAuth.basic_auth(req, res, authlabel) { |user, pass|
if pass.to_s != ''
ldap = Net::LDAP.new
ldap.host = "ldap.serverfoo.com"
ldap.port = 389
result = ldap.bind_as(
:base => "t=basetreefoo",
:filter => "uid=#{user}",
:password => pass
)
if result
ldap = Net::LDAP.new :host => "ldap.serverfoo.com",
:port => "389",
:auth => {
:method => :simple,
:username => "",
:password => ""
}
group_name = Net::LDAP::Filter.eq("cn", "#{user}")
group_type = Net::LDAP::Filter.eq("groupmembership", "cn=infra,ou=IT,o=Corporate")
filter = group_name & group_type
treebase = "t=basetreefoo"
ldap.search(:base => treebase, :filter => filter) do |entry|
if entry.dn.to_s != ""
puts 'success'
return
end
end
end
end
puts 'fail'
}
end
I'm trying to get Paypal SetExpressCheckout operation to add first and last name for billing. I'm using ActiveMerchant. I'm seeing the address field pre-populated (street, state, city,zip-code) but nothing else.
#### gateway ######
gateway = ActiveMerchant::Billing::PaypalExpressGateway.new(:login => 'login',:password => 'pass',:signature => 'sig')
### options ######
#options = Hash.new
#options.merge!(:ip => '127.0.0.1')
#options.merge!(:return_url => '127.0.0.1')
#options.merge!(:return_url => 'http://www.google.com')
#options.merge!(:cancel_return_url => 'http://www.google.com')
#options.merge!(:name => 'name')
#options.merge!(:description => 'description')
#options.merge!(:max_amount => 5000)
#options.merge!(:solution_type => 'Sole')
#options.merge!(:no_shipping => 1)
#options.merge!(:address_override => 1)
### build address
#address = Hash.new
#address.merge!(:name => "Joe User")
#address.merge!(:address1 => "111 ABCD EFG")
#address.merge!(:address2 => nil)
#address.merge!(:city => "Fremont")
#address.merge!(:state => "CA")
#address.merge!(:country => "US")
#address.merge!(:phone => "408-111-2222")
#options.merge!(:address => #address)
setup_response = gateway.setup_purchase(5000, #options)
redirect_to gateway.redirect_url_for(setup_response.token)
On the resultant page, I'm not seeing the name pre-filled for billing.
What am I doing wrong?
Thanks
I had the same issue as you did. After some research I came to the conclusion that this is a bug in ActiveMerchant. Please see the issue that I filed. It includes an explanation of how I patched my code to make phone number and names work:
https://github.com/Shopify/active_merchant/issues/161