{"action":"created","comment":{"url":"https://api.github.com/repos/auth0/blog/pulls/comments/122010959","pull_request_review_id":44086329,"id":122010959,"diff_hunk":"@@ -0,0 +1,312 @@\n+---\n+layout: post\n+title: \"Combining Auth0's Lock with Iris recognition\"\n+description: \"Using Ruby on Rails to combine Auth0 Lock with Iris Recognition for 2 Factor Authentication\"\n+date: 2017-06-08 09:40\n+category: Technical Guide, Backend, Ruby\n+author:\n+  name: \"Robin Percy\"\n+  url: \"https://twitter.com/rbin\"\n+  mail: \"robin@percy.pw\"\n+  avatar: \"https://secure.gravatar.com/avatar/685342d5e7f42c3ab8d251d7d4a53308?s=100&d=mm&r=g\"\n+tags:\n+- 2FA\n+- Ruby\n+- Rails\n+- Image-Recognition\n+---\n+\n+\n+Eyeball\n+======\n+\n+### Combining Auth0's Lock with Iris recognition for 2 Factor Auth\n+\n+\n+## Technology Used\n+ * Ruby / Rails\n+ * Auth0 Lock\n+ * ImageMagick for custom Image Comparison\n+ * Amazon S3\n+ \n+ \n+## What, Why?\n+\n+Social engineering methods are increasingly being used to gain access to User Credentials.  While the provider maybe as secure as can be, they are not always the source of credential leaks.  Obtaining usernames and passwords by effectively 'tricking' people into handing them over is becoming more and more common.\n+\n+If a miscreant is to get hold of your account login details, naturally they will be able to access sensitive data.  Of course, there are already many methods available to combat this, such as mobile 2 factor auth; I wanted to take a slightly different **(more fun)** approach to combat the situation. \n+\n+The idea behind *'Eyeball'* is to offer a multi-factor authentication scenario in which we use Auth0's Lock as first-line login, then upon success offer Iris recognition as second-line.  This means that if a User's account details are compromised, the offender would also have to have access to the User's eyeball.  (Much less likely!)\n+\n+From a technical standpoint, we will be building our own Image Comparison application utilising the ImageMagick subsystem.\n+\n+\n+## Getting Started\n+\n+We will be using Ruby / Rails to build this app.  There is already a fantastic quick-start tutorial available, alongside a sample Rails application on the Auth0 Docs.  Instead of starting from scratch, we will simply download this sample app and iterate on it!\n+\n+Even more handy - Auth0 allow you to download this sample Rails app configured with your Auth0 API Keys already in!  [Head over here to download it.](https://auth0.com/docs/quickstart/webapp/rails)\n+\n+For simplicity, we are going to be making an assumption.  A User can't assign their own Iris image in the first place, and this will be upto an Admin.  This reflects a more realistic enterprise situation, for instance a new employee would have their Iris scanned, then an Admin would add that Iris to their User Profile.  In our application specifically, we will be reflecting this by storing, and accessing a `iris_image_url` in Auth0's metadata.  This is just a path to the User's stored Iris image, that we shall use in comparison to the temporarily uploaded Iris image upon login.\n+\n+\n+## Setting up our second-line defence routes\n+\n+Our sample app already has Auth0's Lock setup and working.  The Rails app also has a Dashboard route setup to be redirected to upon successful login.  We need to setup a new route to act as a go-between after successful login and before the User actually gets to see their Dashboard.\n+\n+Go ahead and run:\n+\n+\t> rails g controller Iris check\n+\n+\n+This will create a new route at `iris/check` that we can redirect to after a successful Auth0 login.  We now need to edit our existing Auth0Controller to reflect this.  Open up `app/controllers/auth0_controller.rb` and update the `callback` method as follows:\n+\n+~~~ ruby\n+def callback\n+  session[:userinfo] = request.env['omniauth.auth']\n+\n+  redirect_to '/iris/check'\n+end\n+~~~\n+\n+If you boot your app, and test the login you should now see we don't get to access our Dashboard, but get sent to our Iris Check page.\n+\n+\n+## Building our Iris Recognition!\n+\n+Now then, let's do something fun - facilitate our makeshift eyeball scanner!\n+\n+While there are many API's available for Image Recognition, there are no simplistic ones available for specifically comparing two images, so we're going to roll our own.  Whereas there are great arguments for choosing to use an existing API instead of building our own, it's a better learning experience in this case to do the latter.\n+\n+Image processing for recognition / comparison is a ***very*** deep topic and can be expanded into Machine Learning and simply get deeper and deeper.  For this article, we'll be building our Image Comparison system without the added benefit of Machine Learning.  In the future, I will expand this article into a series of articles covering Deep Machine Learning.\n+\n+For now, we're going to use the application [ImageMagick](https://github.com/ImageMagick/ImageMagick) for our comparison functionality.  This comes bundled with Ubuntu and is generally widely available.  If you're on a Mac and don't want to download it from the net/app store - you can use `Homebrew`.\n+\n+\t> brew install gs\n+\n+\t> brew install libpng\n+\n+ \t> brew install imagemagick","path":"_posts/2017-06-08-Lock-and-Iris-Recognition-in-ruby-on-rails.markdown","position":89,"original_position":89,"commit_id":"2bd8345938c509d3c59ef88a86f2313f6a19bfac","original_commit_id":"2bd8345938c509d3c59ef88a86f2313f6a19bfac","user":{"login":"sebadoom","id":773367,"avatar_url":"https://avatars3.githubusercontent.com/u/773367?v=3","gravatar_id":"","url":"https://api.github.com/users/sebadoom","html_url":"https://github.com/sebadoom","followers_url":"https://api.github.com/users/sebadoom/followers","following_url":"https://api.github.com/users/sebadoom/following{/other_user}","gists_url":"https://api.github.com/users/sebadoom/gists{/gist_id}","starred_url":"https://api.github.com/users/sebadoom/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sebadoom/subscriptions","organizations_url":"https://api.github.com/users/sebadoom/orgs","repos_url":"https://api.github.com/users/sebadoom/repos","events_url":"https://api.github.com/users/sebadoom/events{/privacy}","received_events_url":"https://api.github.com/users/sebadoom/received_events","type":"User","site_admin":false},"body":"Is it necessary to install `libpng` and `gs` manually?","created_at":"2017-06-14T17:22:52Z","updated_at":"2017-06-14T18:00:50Z","html_url":"https://github.com/auth0/blog/pull/869#discussion_r122010959","pull_request_url":"https://api.github.com/repos/auth0/blog/pulls/869","_links":{"self":{"href":"https://api.github.com/repos/auth0/blog/pulls/comments/122010959"},"html":{"href":"https://github.com/auth0/blog/pull/869#discussion_r122010959"},"pull_request":{"href":"https://api.github.com/repos/auth0/blog/pulls/869"}}},"pull_request":{"url":"https://api.github.com/repos/auth0/blog/pulls/869","id":125372207,"html_url":"https://github.com/auth0/blog/pull/869","diff_url":"https://github.com/auth0/blog/pull/869.diff","patch_url":"https://github.com/auth0/blog/pull/869.patch","issue_url":"https://api.github.com/repos/auth0/blog/issues/869","number":869,"state":"open","locked":false,"title":"Auth0 Lock and Iris Detection for 2FA in Rails","user":{"login":"rbnpercy","id":29288325,"avatar_url":"https://avatars3.githubusercontent.com/u/29288325?v=3","gravatar_id":"","url":"https://api.github.com/users/rbnpercy","html_url":"https://github.com/rbnpercy","followers_url":"https://api.github.com/users/rbnpercy/followers","following_url":"https://api.github.com/users/rbnpercy/following{/other_user}","gists_url":"https://api.github.com/users/rbnpercy/gists{/gist_id}","starred_url":"https://api.github.com/users/rbnpercy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rbnpercy/subscriptions","organizations_url":"https://api.github.com/users/rbnpercy/orgs","repos_url":"https://api.github.com/users/rbnpercy/repos","events_url":"https://api.github.com/users/rbnpercy/events{/privacy}","received_events_url":"https://api.github.com/users/rbnpercy/received_events","type":"User","site_admin":false},"body":"","created_at":"2017-06-13T14:04:30Z","updated_at":"2017-06-14T18:00:50Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1ee4f9bffa60008b84c30ca0070555fffb98d70a","assignee":null,"assignees":[],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/auth0/blog/pulls/869/commits","review_comments_url":"https://api.github.com/repos/auth0/blog/pulls/869/comments","review_comment_url":"https://api.github.com/repos/auth0/blog/pulls/comments{/number}","comments_url":"https://api.github.com/repos/auth0/blog/issues/869/comments","statuses_url":"https://api.github.com/repos/auth0/blog/statuses/2bd8345938c509d3c59ef88a86f2313f6a19bfac","head":{"label":"rbnpercy:rbnpercy-lock-iris-app","ref":"rbnpercy-lock-iris-app","sha":"2bd8345938c509d3c59ef88a86f2313f6a19bfac","user":{"login":"rbnpercy","id":29288325,"avatar_url":"https://avatars3.githubusercontent.com/u/29288325?v=3","gravatar_id":"","url":"https://api.github.com/users/rbnpercy","html_url":"https://github.com/rbnpercy","followers_url":"https://api.github.com/users/rbnpercy/followers","following_url":"https://api.github.com/users/rbnpercy/following{/other_user}","gists_url":"https://api.github.com/users/rbnpercy/gists{/gist_id}","starred_url":"https://api.github.com/users/rbnpercy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rbnpercy/subscriptions","organizations_url":"https://api.github.com/users/rbnpercy/orgs","repos_url":"https://api.github.com/users/rbnpercy/repos","events_url":"https://api.github.com/users/rbnpercy/events{/privacy}","received_events_url":"https://api.github.com/users/rbnpercy/received_events","type":"User","site_admin":false},"repo":{"id":94218448,"name":"blog","full_name":"rbnpercy/blog","owner":{"login":"rbnpercy","id":29288325,"avatar_url":"https://avatars3.githubusercontent.com/u/29288325?v=3","gravatar_id":"","url":"https://api.github.com/users/rbnpercy","html_url":"https://github.com/rbnpercy","followers_url":"https://api.github.com/users/rbnpercy/followers","following_url":"https://api.github.com/users/rbnpercy/following{/other_user}","gists_url":"https://api.github.com/users/rbnpercy/gists{/gist_id}","starred_url":"https://api.github.com/users/rbnpercy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rbnpercy/subscriptions","organizations_url":"https://api.github.com/users/rbnpercy/orgs","repos_url":"https://api.github.com/users/rbnpercy/repos","events_url":"https://api.github.com/users/rbnpercy/events{/privacy}","received_events_url":"https://api.github.com/users/rbnpercy/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/rbnpercy/blog","description":"auth0 blog","fork":true,"url":"https://api.github.com/repos/rbnpercy/blog","forks_url":"https://api.github.com/repos/rbnpercy/blog/forks","keys_url":"https://api.github.com/repos/rbnpercy/blog/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rbnpercy/blog/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rbnpercy/blog/teams","hooks_url":"https://api.github.com/repos/rbnpercy/blog/hooks","issue_events_url":"https://api.github.com/repos/rbnpercy/blog/issues/events{/number}","events_url":"https://api.github.com/repos/rbnpercy/blog/events","assignees_url":"https://api.github.com/repos/rbnpercy/blog/assignees{/user}","branches_url":"https://api.github.com/repos/rbnpercy/blog/branches{/branch}","tags_url":"https://api.github.com/repos/rbnpercy/blog/tags","blobs_url":"https://api.github.com/repos/rbnpercy/blog/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rbnpercy/blog/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rbnpercy/blog/git/refs{/sha}","trees_url":"https://api.github.com/repos/rbnpercy/blog/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rbnpercy/blog/statuses/{sha}","languages_url":"https://api.github.com/repos/rbnpercy/blog/languages","stargazers_url":"https://api.github.com/repos/rbnpercy/blog/stargazers","contributors_url":"https://api.github.com/repos/rbnpercy/blog/contributors","subscribers_url":"https://api.github.com/repos/rbnpercy/blog/subscribers","subscription_url":"https://api.github.com/repos/rbnpercy/blog/subscription","commits_url":"https://api.github.com/repos/rbnpercy/blog/commits{/sha}","git_commits_url":"https://api.github.com/repos/rbnpercy/blog/git/commits{/sha}","comments_url":"https://api.github.com/repos/rbnpercy/blog/comments{/number}","issue_comment_url":"https://api.github.com/repos/rbnpercy/blog/issues/comments{/number}","contents_url":"https://api.github.com/repos/rbnpercy/blog/contents/{+path}","compare_url":"https://api.github.com/repos/rbnpercy/blog/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rbnpercy/blog/merges","archive_url":"https://api.github.com/repos/rbnpercy/blog/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rbnpercy/blog/downloads","issues_url":"https://api.github.com/repos/rbnpercy/blog/issues{/number}","pulls_url":"https://api.github.com/repos/rbnpercy/blog/pulls{/number}","milestones_url":"https://api.github.com/repos/rbnpercy/blog/milestones{/number}","notifications_url":"https://api.github.com/repos/rbnpercy/blog/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rbnpercy/blog/labels{/name}","releases_url":"https://api.github.com/repos/rbnpercy/blog/releases{/id}","deployments_url":"https://api.github.com/repos/rbnpercy/blog/deployments","created_at":"2017-06-13T13:53:27Z","updated_at":"2017-06-13T13:53:31Z","pushed_at":"2017-06-13T14:02:51Z","git_url":"git://github.com/rbnpercy/blog.git","ssh_url":"git@github.com:rbnpercy/blog.git","clone_url":"https://github.com/rbnpercy/blog.git","svn_url":"https://github.com/rbnpercy/blog","homepage":"https://auth0.com/blog","size":18883,"stargazers_count":0,"watchers_count":0,"language":"HTML","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"auth0:master","ref":"master","sha":"a840f52de8e43723847e47eacba270e67622100b","user":{"login":"auth0","id":2824157,"avatar_url":"https://avatars2.githubusercontent.com/u/2824157?v=3","gravatar_id":"","url":"https://api.github.com/users/auth0","html_url":"https://github.com/auth0","followers_url":"https://api.github.com/users/auth0/followers","following_url":"https://api.github.com/users/auth0/following{/other_user}","gists_url":"https://api.github.com/users/auth0/gists{/gist_id}","starred_url":"https://api.github.com/users/auth0/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/auth0/subscriptions","organizations_url":"https://api.github.com/users/auth0/orgs","repos_url":"https://api.github.com/users/auth0/repos","events_url":"https://api.github.com/users/auth0/events{/privacy}","received_events_url":"https://api.github.com/users/auth0/received_events","type":"Organization","site_admin":false},"repo":{"id":7830124,"name":"blog","full_name":"auth0/blog","owner":{"login":"auth0","id":2824157,"avatar_url":"https://avatars2.githubusercontent.com/u/2824157?v=3","gravatar_id":"","url":"https://api.github.com/users/auth0","html_url":"https://github.com/auth0","followers_url":"https://api.github.com/users/auth0/followers","following_url":"https://api.github.com/users/auth0/following{/other_user}","gists_url":"https://api.github.com/users/auth0/gists{/gist_id}","starred_url":"https://api.github.com/users/auth0/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/auth0/subscriptions","organizations_url":"https://api.github.com/users/auth0/orgs","repos_url":"https://api.github.com/users/auth0/repos","events_url":"https://api.github.com/users/auth0/events{/privacy}","received_events_url":"https://api.github.com/users/auth0/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/auth0/blog","description":"auth0 blog","fork":false,"url":"https://api.github.com/repos/auth0/blog","forks_url":"https://api.github.com/repos/auth0/blog/forks","keys_url":"https://api.github.com/repos/auth0/blog/keys{/key_id}","collaborators_url":"https://api.github.com/repos/auth0/blog/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/auth0/blog/teams","hooks_url":"https://api.github.com/repos/auth0/blog/hooks","issue_events_url":"https://api.github.com/repos/auth0/blog/issues/events{/number}","events_url":"https://api.github.com/repos/auth0/blog/events","assignees_url":"https://api.github.com/repos/auth0/blog/assignees{/user}","branches_url":"https://api.github.com/repos/auth0/blog/branches{/branch}","tags_url":"https://api.github.com/repos/auth0/blog/tags","blobs_url":"https://api.github.com/repos/auth0/blog/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/auth0/blog/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/auth0/blog/git/refs{/sha}","trees_url":"https://api.github.com/repos/auth0/blog/git/trees{/sha}","statuses_url":"https://api.github.com/repos/auth0/blog/statuses/{sha}","languages_url":"https://api.github.com/repos/auth0/blog/languages","stargazers_url":"https://api.github.com/repos/auth0/blog/stargazers","contributors_url":"https://api.github.com/repos/auth0/blog/contributors","subscribers_url":"https://api.github.com/repos/auth0/blog/subscribers","subscription_url":"https://api.github.com/repos/auth0/blog/subscription","commits_url":"https://api.github.com/repos/auth0/blog/commits{/sha}","git_commits_url":"https://api.github.com/repos/auth0/blog/git/commits{/sha}","comments_url":"https://api.github.com/repos/auth0/blog/comments{/number}","issue_comment_url":"https://api.github.com/repos/auth0/blog/issues/comments{/number}","contents_url":"https://api.github.com/repos/auth0/blog/contents/{+path}","compare_url":"https://api.github.com/repos/auth0/blog/compare/{base}...{head}","merges_url":"https://api.github.com/repos/auth0/blog/merges","archive_url":"https://api.github.com/repos/auth0/blog/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/auth0/blog/downloads","issues_url":"https://api.github.com/repos/auth0/blog/issues{/number}","pulls_url":"https://api.github.com/repos/auth0/blog/pulls{/number}","milestones_url":"https://api.github.com/repos/auth0/blog/milestones{/number}","notifications_url":"https://api.github.com/repos/auth0/blog/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/auth0/blog/labels{/name}","releases_url":"https://api.github.com/repos/auth0/blog/releases{/id}","deployments_url":"https://api.github.com/repos/auth0/blog/deployments","created_at":"2013-01-25T22:57:37Z","updated_at":"2017-06-13T09:13:37Z","pushed_at":"2017-06-14T15:08:22Z","git_url":"git://github.com/auth0/blog.git","ssh_url":"git@github.com:auth0/blog.git","clone_url":"https://github.com/auth0/blog.git","svn_url":"https://github.com/auth0/blog","homepage":"https://auth0.com/blog","size":18950,"stargazers_count":34,"watchers_count":34,"language":"HTML","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":62,"mirror_url":null,"open_issues_count":42,"forks":62,"open_issues":42,"watchers":34,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/auth0/blog/pulls/869"},"html":{"href":"https://github.com/auth0/blog/pull/869"},"issue":{"href":"https://api.github.com/repos/auth0/blog/issues/869"},"comments":{"href":"https://api.github.com/repos/auth0/blog/issues/869/comments"},"review_comments":{"href":"https://api.github.com/repos/auth0/blog/pulls/869/comments"},"review_comment":{"href":"https://api.github.com/repos/auth0/blog/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/auth0/blog/pulls/869/commits"},"statuses":{"href":"https://api.github.com/repos/auth0/blog/statuses/2bd8345938c509d3c59ef88a86f2313f6a19bfac"}}}}
{"actor":{"display_login":"sebadoom"}}