{"id":21515645,"url":"https://github.com/sqreen/devise_sqreener","last_synced_at":"2025-04-09T20:12:30.381Z","repository":{"id":59152885,"uuid":"82091569","full_name":"sqreen/devise_sqreener","owner":"sqreen","description":"Get more information about devise users through sqreen enrich","archived":false,"fork":false,"pushed_at":"2017-06-06T09:17:52.000Z","size":115,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-09T20:12:23.745Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sqreen.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-02-15T18:19:20.000Z","updated_at":"2018-07-05T00:31:45.000Z","dependencies_parsed_at":"2022-09-13T11:01:20.961Z","dependency_job_id":null,"html_url":"https://github.com/sqreen/devise_sqreener","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqreen%2Fdevise_sqreener","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqreen%2Fdevise_sqreener/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqreen%2Fdevise_sqreener/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqreen%2Fdevise_sqreener/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sqreen","download_url":"https://codeload.github.com/sqreen/devise_sqreener/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248103872,"owners_count":21048245,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-23T23:56:11.014Z","updated_at":"2025-04-09T20:12:30.333Z","avatar_url":"https://github.com/sqreen.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# devise_sqreener\n\nNot everyone who signs up for your app wants to use your service. Wouldn’t it be nice if there was an easy way to automatically block abusers? `devise_sqreener` is a [Devise](https://github.com/plataformatec/devise) extension that adds the ability to block or flag potentially malicious users of your Rails app.\n\nWhenever a new user signs up or signs in, their IP address and email address are compared against Sqreen's extensive database of bad apples; you get back a chunk of actionable metadata on those addresses that can be used to set user policies. You can, for example:\n\n* Block users with a history of malicious abuse from signing up\n* Prevent users from signing in over TOR.\n* Discover whether someone is logging in from two distinct geographic locations at the same time.\n* Flag users signing up with disposable email addresses.\n\nSuch fun!\n\n## Prerequisites\n\nBeing a [Devise](https://github.com/plataformatec/devise) extension, we assume that you are using Rails, and, yes, Devise.\n\n## Install\n\nOf course, the best way to install is with RubyGems! Add this line to your application's Gemfile:\n\n```ruby\ngem 'devise_sqreener'\n```\n\nand then execute\n```bash\n$ bundle\n```\n\nto download the latest version and install it.\n\n## Set up\n\nLet's assume your user model is called `User`.\n\nFirst we should note that `devise_sqreener` relies on the Devise `:trackable` strategy for tracking IP addresses. By default, `:trackable` is enabled, but if your use model doesn't include `:trackable`, and you want to enable the IP address filtering features, then you'll need to re-enable `:trackable`. Doing that is a bit beyond the scope of this tutorial, unfortunately. Anyway, the default Devise User model looks something like this, for reference purposes.\n\n```ruby\nclass User \u003c ActiveRecord::Base\n  # Include default devise modules. Others available are:\n  # :confirmable, :lockable, :timeoutable and :omniauthable\n  devise :database_authenticatable, :registerable,\n         :recoverable, :rememberable, :trackable, :validatable\nend\n```\nOK, so that out of the way, let's add `devise_sqreener` to the `User` model using the following generator:\n\n```bash\n$ rails generate devise_sqreener User\n```\n\nThis will add the `:sqreenable` flag to your `User` model, and some new fields in the User table of your database. The generator will also create a migration file. Currently only ActiveRecord is supported.\n\nLet's get that migration knocked out, then? Run:\n\n```bash\n$ rails db:migrate\n```\n\n## Get your API token\n\nFor the automatic sqreening to work you need to provide [your Sqreen API token](https://my.sqreen.io) in your Devise configuration, `config/initializers/devise.rb`. You might need to create an account on Sqreen—and once you do you can choose between the 14-day free trial for the full product and the forever-free API Sandbox; if you just want to get straight to the API, choose the API Sandbox. The API Sandboxes are free forever, albeit rate-limited and with a limited number of requests per month. That will do for our current purposes nicely.\n\nNow, to put that API key to use. We're not going to advocate for just leaving your API credentials in your code. Ha, of course not. No, we're going to pass it in as an environment variable. So add the following *_verbatim_* to the bottom of your Devise configuration.\n\n```ruby\nDevise.setup do |config|\n  #...\n  config.sqreen_api_token=ENV[\"SQREEN_API_TOKEN\"]  # \u003c- DO NOT PUT YOUR API TOKEN HERE!\n  #...\nend\n```\n\nAnd pass it in to your app's runtime environment with something like\n\n```\nexport SQREEN_API_TOKEN=\"PASTE_YOUR_TOKEN_HERE\"\n```\n\nThere are lots of ways to get environment variables into your Rails app, of course—you should follow the practices used for your particular app if they aren't set in this way.\n\n## Create your user Sqreening policy\n\n\"Sqreening\"? Get it? It's funny.\n\nSqreening policies are implemented as predicates in your Devise configuration, `config/initializers/devise.rb`. There are two predicates, one for signing up and one for signing in. The predicates can do really anything you like, including firing off notifications, or flagging the user in some way. But the most important thing is deciding whether to block the user from completing the sign-up or sign-in action.\n\nThe arguments to the predicates are:\n* `email`: Current email sqreened metadata (a Hash or nil)\n* `ip`: Current ip address sqreened metadata (a Hash or nil)\n* `user`: The current instance of your MODEL class trying to sign in/up.\n\nThe return value should be a boolean. If your predicate returns `true`, the action will be blocked. If your predicate returns `false`, the action will not be blocked.\n\nThe `email` hash passed to the predicate has the following structure:\n\n* `email`: string The email address queried.\n* `risk_score`: number The assessed risk that this email address is being used by a malevolent actor. Values range from 0 to 100. Anything greater than 80 is really bad and should be dropped; anything greater than about 40 is worth flagging and keeping an eye on.\n* `is_email_harmful`: boolean Does the email address itself pose a direct security risk? E.g., does the email address contain embedded JavaScript?\n* `is_known_attacker`: boolean Was this email address used as part of a security attack?\n* `high_risk_security_events_count`: number The number of high-risk security events (e.g. SQL injection attacks) involving this email address.\n* `security_events_count`: number The number of all security events (both high-risk and low-risk) involving this email address.\n* `is_disposable`: boolean Does this email's domain belong to a known vendor of disposable, temporary, or anonymized email addresses?\n* `is_email_malformed`: boolean Is the email malformed according to RFC 5322?\n\nThe `ip` hash passed to the predicate has the following structure:\n\n* `ip`: string The IP address queried.\n* `ip_version`: number The version of the IP address queried. Either 4 or 6.\n* `risk_score`: number The assessed risk that this IP address is being used by a malevolent actor. Values range from 0 to 100. Anything greater than 80 is really bad and should be dropped; anything greater than about 40 is worth flagging and keeping an eye on.\n* `is_known_attacker`: boolean Was this IP address used as part of a security attack?\n* `high_risk_security_events_count`: number The number of high-risk security events (e.g. SQL injection attacks) originating from this IP address.\n* `security_events_count`: number The number of all security events (both high-risk and low-risk) originating from this IP address.\n* `ip_geo`: object The geographical location associated with this IP address.\n* `ip_geo.latitude` number The latitude of the location.\n* `ip_geo.longitude `number The longitude of the location.\n* `ip_geo.country_code` string The ISO ALPHA-3 Code for the country that this location exists within.\n* `is_datacenter`: boolean Does this IP address belong to a known datacenter, such as AWS or Google Cloud?\n* `is_vpn`: boolean Does this IP address belong to a known VPN?\n* `is_proxy`: boolean Does this IP address belong to a known proxy server?\n* `is_tor`: boolean Is this IP address a known Tor exit point?\n\nLet's suppose that we want to block all sign-ups and sign-ins over TOR:\n\n```ruby\nDevise.setup do |config|\n  #...\n  # Block signing in from TOR\n  config.sqreen_block_sign_in =  -\u003e (email, ip, user)  {ip \u0026\u0026 ip[\"is_tor\"] }\n  # Block signing up from TOR \n  config.sqreen_block_sign_up =  -\u003e (email, ip, user)  {ip \u0026\u0026 ip[\"is_tor\"] }\n  #...\nend\n```\n\nOr perhaps you just want to look at Sqreen's pre-calculated risk score for the email address to make this determination:\n```ruby\nDevise.setup do |config|\n  #...\n  # Block signing up with a risky email address \n  config.sqreen_block_sign_up =  -\u003e (email, ip, user)  {email \u0026\u0026 email[\"risk_score\"] \u003e 70 }\n  #...\nend\n```\n\nAnd of course the metadata retrieved from Sqreen is saved to the `User` model as serialized data, so you can look it up any time you like, and take further action later.\n\n![Activeadmin Screenshot](/doc/activeadmin.png)\n\nThe possibilities are...well, let's be honest, they're not exactly endless, but there is a great deal of flexibility in crafting these policies.\n\n## Let us know how it works for you\n\nSo, that's about all there is to it! Having a problem? Have an idea for how we could improve this Devise plugin? [Open an issue](https://github.com/sqreen/devise_sqreener/issues/new), and let us know what we can do better. ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsqreen%2Fdevise_sqreener","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsqreen%2Fdevise_sqreener","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsqreen%2Fdevise_sqreener/lists"}