YOUR (RAILS) APP ONTHE GOOGLE APPSMARKETPLACELessons learned from integratingFraudpointer
Should I be interested? Scenario 1 : You are a SaaS vendor Your application is organization oriented (users belong to groups / organizations) Scenario 2 (with some constraints / changes) : Same as 1 but user oriented Scenario 3 : Your organization is using Google Apps You have custom applications with “admin” sections
Presentation Outline What is Google Apps ™ / Marketplace What is Fraudpointer / Fraudpointer integration points Bootstrapping Dev environment Integrating Gotchas Further work Resources Acknowledgements Q/A
Google Apps Marketplace Thousands of applications that integrate with Google Apps accounts You search, pick, ad d and use Payment either transparent through the Marketplace or independently through the Vendors
Google Apps Marketplace Applications added to your Google Apps account are added organization-wide Applications added to your Google Apps account gain restricted access to your Google user’s data Only admins can add new applications
Google Apps Marketplace As a vendor you sell your own applications
Fraudpointer Fraud prevention platform Credit card fraud Account phising Digital rights misuse … SaaS A tool to be used alongside existing “enterprise” tools like E-Commerce platform CRM ERP Productivity / communication tools (Google Apps!)
Fraudpointer Major components Account setup & configuration Fraud Assessment API Rule Engine Reputation Database Case Management …
Fraudpointer Integration Major components Account setup & configuration Fraud Assessment API Rule Engine Reputation Database Case Management …
Fraudpointer Integration One click account creation & setup Single Sign On Gmail & Contacts integration Rule engine lists management from Google Spreadsheets Cases exporting to Google Spreadsheets
Fraudpointer Integration One click account creation & setup Provisioning API (Read) Single Sign On OAuth Gmail & Contacts integration Gmail API (Read/Write/Send) Contacts API (Read) Rule engine lists management from Google Spreadsheets Spreadsheets API (Read/Write) Docs API (Read/ Write) Cases exporting to Google Spreadsheets Spreadsheets API (Read/Write) Docs API (Read/Write)
Bootstrapping Google Apps account Not a @gmail one – a custom domain one! Free or paid Permissions to install applications on your Google Apps domain (needed during development)
Act as a vendor You will act as a Vendor, selling your application This is true both for live / development phase GOTCHA : Vendor profiles “per user”. Not “per domain”
Add a listing Create a new listing in your Vendor profile This is what you are selling
Listing details Application manifest is the most important thing Listing manifest is not required!
Application Manifest Best practices Declare the various API scopes in your code Automatically generate the URLs from Rails helpers Copy-paste the generated xml to the listing Gotchas Watch out for whitespaces & blank lines before/after the actual XML! Totally stupid listing form with totally stupid validation errors!
Listing save & preview Save & preview without fear – nobody will see Ignore the Analytics id and the Google APIs
Add it to start development! Don’t submit Just “Add it now” This is your development installation This is the same experience your users will have!
Addition is a 2-phase process When “agree” is pressed application is “added” No access to data yet! No configuration yet!
Addition is a 2-phase process Granting data access Read from the application manifest
Setup/Configuration (optional) Application has access Knows nothing (yet) about it’s addition though! This is where you “hook” and bootstrap the account!
Setup/Configuration (optional) The Google Apps admin sees a configuration screen Selects users / groups to import Configures other account settings The alternative is to import all Google Apps users (ouch!)
Development environment Hack your hosts so redirects / URLs are not “localhost”! Get a Google Apps account! One “installation” per developer (doesn’t scale really…)
Single Sign On Required integration point Based on OpenID Google is an OpenID Identity Provider via the OpenID Federated Login Service Fraudpointer acts as an OpenID Relying Party Google’s OpenID implementation : http://code.google.com/googleapps/domain/sso/openid_refer ence_implementation.html With Federated Login enabled, Google Apps users authenticate with OpenID to Fraudpointer Attention to the Discovery Mechanism : https://sites.google.com/site/oauthgoog/fedlogininterp/openid discovery
OpenID Authentication Proves an end user “controls” an “identifier” Simply put : one account – login to multiple sites! Relying Party doesn’t require access to end user credentials (such as password) User just types one piece of information (such as OpenID identifier)
OpenID Authentication Read guidelines for UI Use an existing library! Ruby has ruby-openid https://github.com/openid/ruby-openid Both for Relying Party & Provider BTW, Fraudpointer does not use it directly and neither should you!
Single Sign On *Should* work out of the box with : rack-openid HTTPish API around ruby-openid Uses ruby-openid internally ruby-openid-apps-discovery Support for Google’s discovery mechanism
Single Sign Onrequire gapps_openid # ....this is from ruby-openid-apps-discoveryrequire rack/openid # ....this is from rack-openid# ... inside the method that handles your login ...# you essentially respond with requirement to authenticate# since the user is considered unauthorized. You also provide# a callback URL and method so that when authentication ends# you take back the control. Discovery and the whole authentication# process is transparent to your code. You do not have to do anything# more than this.#headers[WWW-Authenticate] = Rack::OpenID.build_header( :identifier => options[:open_id], :required => ["http://axschema.org/contact/email", "http://axschema.org/namePerson/first", "http://axschema.org/namePerson/last"], :return_to => url_for(options[:return_to_options]), :method => options[:return_to_method])render :nothing => true, :status => :unauthorized
Single Sign Onrequest.env["rack.openid.response"]will have information about the success or failure of theauthentication.1st make sure that nothing of the following is falseparams[:open_id].blank? ||request.env["rack.openid.response"].nil? ||request.env["rack.openid.response"].status != :successIf everything ok, then you can be sure that user hasbeen authenticated and you can get his data andredirect to your home page:ax = OpenID::AX::FetchResponse.from_success_response(request.env["rack.openid.response"])@email = ax.get_single("http://axschema.org/contact/email")@first_name = ax.get_single("http://axschema.org/namePerson/first")@last_name = ax.get_single("http://axschema.org/namePerson/last")
Authorization oauth two-legged-oauth Fraudpointer is a “consumer”
Access to Google Data APIs 2-legged Oauth is the source of the biggest confusion! On normal situations (no Google Apps) : A Google user (firstname.lastname@example.org) grants access to a 3rd party application (freemium- sass.com) for their data 3rd party application can now access this user’s data So for example, freemium-saas has access to all of the user’s Google Documents
Access to Google Data APIs On Google Apps situation is different A Google Apps domain administrator grants access for the all the domain’s users data to a 3rd party application (enterprise-saas.com) 3rd party application plays the role of the currently logged in user by sending the identity of the user (xoauth_requestor_id) The current instance of the 3rd party application has same access to data as the requesting user would have The real user has no way of restraining access to his data for this app (only the admin)
Access to Google Data APIs Normal requests to Google Data APIs are like this : https://docs.google.com/feeds/user@yourdom ain.com/private/full/ But for Google Apps using 2-legged Oauth it becomes this : https://docs.google.com/feeds/user@yourdom ain.com/private/full?xoauth_requestor_id=ad email@example.com
two-legged-oauth gem Transparent hack for all Ruby Google APIs libraries with OAuth support Rewriting on the fly the URLs so that it contains the magic “xoauth_requestor_id” parameter Ugly but seems to work so far (thus the 0.0.2 version) @!#$!@#$%%#$@ (yeah a lot of yelling, crying and bleeding because of this) Feel free to improve it!
Authorization (using the libs) Create OAuth::Consumer with key and secret Request (on Consumer) a request token Request (on Request Token) an access token On access token give as parameter the API resource you want to access Resource should be included in the manifest
Authorization and accessconsumer = OAuth::Consumer.new( Settings.google_apps.consumer_key, Settings.google_apps.consumer_key_secret)OAuth::TwoLeggedAccessToken.new(consumer, self.email)GoogleContactsApi::User.new(google_apps_access_token).contacts
Authorization - Scopes Data access to Google requires correct Scopes Scopes correspond to Google APIs Examples : Contacts API : https://www.google.com/m8/feeds/ Spreadsheets API : https://spreadsheets.google.com/feeds/ Some resources are “read only”