authful 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/Guardfile +15 -0
- data/LICENSE.txt +22 -0
- data/README.md +51 -0
- data/Rakefile +1 -0
- data/authful.gemspec +29 -0
- data/lib/authful/response.rb +11 -0
- data/lib/authful/user.rb +109 -0
- data/lib/authful/version.rb +5 -0
- data/lib/authful.rb +41 -0
- data/spec/lib/authful/user_spec.rb +112 -0
- data/spec/spec_helper.rb +4 -0
- metadata +174 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard :bundler do
|
5
|
+
watch('Gemfile')
|
6
|
+
watch(/^.+\.gemspec/)
|
7
|
+
end
|
8
|
+
|
9
|
+
guard :rspec do
|
10
|
+
watch(%r{^spec/.+_spec\.rb$})
|
11
|
+
watch('lib/authful.rb')
|
12
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
13
|
+
watch('spec/spec_helper.rb') { "spec" }
|
14
|
+
end
|
15
|
+
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Chris Winslett
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# Authful Ruby Client
|
2
|
+
|
3
|
+
Makes integration with 2fa as simple as possible. This gem interacts
|
4
|
+
with the open-sourced [Authful service](https://github.com/MongoHQ/authful) for 2fa.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
gem 'authful'
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
$ gem install authful
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
To use, you will need an Authful endpoint. You will need to install it,
|
23
|
+
or if a successful project, you will probably find Authful endpoint as a
|
24
|
+
service.
|
25
|
+
|
26
|
+
To configure the gem, use:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
Authful.configure do |c|
|
30
|
+
c.endpoint = "https://<myendpoint>"
|
31
|
+
c.api_key = "<my api key>"
|
32
|
+
end
|
33
|
+
|
34
|
+
res = Authful.enroll("emailaddress@gmail.com", "12055555505")
|
35
|
+
res.qr_code # use this to display the QR code for the user signup
|
36
|
+
res.token # You will want to save this token to your application, it is
|
37
|
+
# the user's primary key to the authful service. It is **not**
|
38
|
+
# the secret token used to generate OTP.
|
39
|
+
|
40
|
+
|
41
|
+
Authful.send_sms("token") # sends sms token
|
42
|
+
Authful.validate("token", "000000") # validates OTP token
|
43
|
+
Authful.unenroll("token") # Remove user from Authful service
|
44
|
+
```
|
45
|
+
## Contributing
|
46
|
+
|
47
|
+
1. Fork it
|
48
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
49
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
50
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
51
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/authful.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'authful/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "authful"
|
8
|
+
spec.version = Authful::Client::VERSION
|
9
|
+
spec.authors = ["Chris Winslett"]
|
10
|
+
spec.email = ["chris@mongohq.com"]
|
11
|
+
spec.description = %q{A wrapper for the Authful service}
|
12
|
+
spec.summary = %q{Both authful is an open source tool that enables rapid implementation of 2fa for your application. This is the client for the service.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'rest-client'
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency "guard-rspec"
|
26
|
+
spec.add_development_dependency "guard-bundler"
|
27
|
+
spec.add_development_dependency "fakeweb"
|
28
|
+
spec.add_development_dependency "pry-debugger"
|
29
|
+
end
|
data/lib/authful/user.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
module Authful
|
2
|
+
class User
|
3
|
+
attr_accessor :token, :email, :phone, :error, :qr_code
|
4
|
+
|
5
|
+
def self.[](token)
|
6
|
+
self.new(token: token)
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(args)
|
10
|
+
args.each do |k,v|
|
11
|
+
instance_variable_set("@#{k}", v) unless v.nil?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def save
|
16
|
+
r = post("/api/users", {email: email, phone: phone})
|
17
|
+
self.qr_code = r["qr_code"]
|
18
|
+
self.token = r["token"]
|
19
|
+
rescue
|
20
|
+
if Authful::Errors::IncorrectApiToken === $!
|
21
|
+
raise Authful::Errors::IncorrectApiToken
|
22
|
+
elsif $!.http_code == 409 # Catch duplicate user -- already enrolled
|
23
|
+
r = JSON.parse($!.response)
|
24
|
+
self.token = r["token"]
|
25
|
+
elsif $!.http_code == 400
|
26
|
+
r = JSON.parse($!.response)
|
27
|
+
self.error = r["error"]
|
28
|
+
false
|
29
|
+
else
|
30
|
+
raise $!
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.create!(args)
|
35
|
+
self.new(args).save
|
36
|
+
end
|
37
|
+
|
38
|
+
def destroy
|
39
|
+
delete("/api/users/#{token}")["ok"] == 1
|
40
|
+
end
|
41
|
+
|
42
|
+
def send_sms
|
43
|
+
get("/api/users/#{token}/send_sms")["ok"] == 1
|
44
|
+
rescue
|
45
|
+
if Authful::Errors::IncorrectApiToken === $!
|
46
|
+
raise Authful::Errors::IncorrectApiToken
|
47
|
+
elsif $!.http_code == 400
|
48
|
+
r = JSON.parse($!.response)
|
49
|
+
self.error = r["error"]
|
50
|
+
false
|
51
|
+
else
|
52
|
+
raise $!
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def valid?(otp_token)
|
57
|
+
get("/api/users/#{token}/validate?token=#{otp_token}")["ok"] == 1
|
58
|
+
rescue
|
59
|
+
if Authful::Errors::IncorrectApiToken === $!
|
60
|
+
raise Authful::Errors::IncorrectApiToken
|
61
|
+
elsif $!.http_code == 403
|
62
|
+
r = JSON.parse($!.response)
|
63
|
+
self.error = r["error"]
|
64
|
+
false
|
65
|
+
else
|
66
|
+
raise $!
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
def get(path)
|
72
|
+
r = RestClient.get url_for(path), headers
|
73
|
+
JSON.parse(r)
|
74
|
+
rescue
|
75
|
+
capture_common_errors($!)
|
76
|
+
end
|
77
|
+
|
78
|
+
def delete(path)
|
79
|
+
r = RestClient.delete url_for(path), headers
|
80
|
+
JSON.parse(r)
|
81
|
+
rescue
|
82
|
+
capture_common_errors($!)
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
def post(path, data)
|
87
|
+
r = RestClient.post url_for(path), data, headers
|
88
|
+
JSON.parse(r)
|
89
|
+
rescue
|
90
|
+
capture_common_errors($!)
|
91
|
+
end
|
92
|
+
|
93
|
+
def capture_common_errors(error)
|
94
|
+
if error.http_code == 401
|
95
|
+
raise Authful::Errors::IncorrectApiToken
|
96
|
+
else
|
97
|
+
raise error
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def url_for(path)
|
102
|
+
[Authful.config.endpoint, path].join("")
|
103
|
+
end
|
104
|
+
|
105
|
+
def headers
|
106
|
+
{"Api-Token" => Authful.config.api_key}
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/lib/authful.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'rest-client'
|
3
|
+
|
4
|
+
module Authful
|
5
|
+
@config = Struct.new(:endpoint, :api_key).new
|
6
|
+
|
7
|
+
def self.configure(&block)
|
8
|
+
block.call(@config)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.config
|
12
|
+
@config
|
13
|
+
end
|
14
|
+
|
15
|
+
## API Calls
|
16
|
+
|
17
|
+
def self.enroll(email, phone)
|
18
|
+
u = Authful::User.new(email: email, phone: phone)
|
19
|
+
u.save
|
20
|
+
return Authful::Response.new(token: u.token, qr_code: u.qr_code, error: u.error)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.validate(token, otp)
|
24
|
+
Authful::User[token].valid?(otp)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.send_sms(token)
|
28
|
+
Authful::User[token].send_sms
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.unenroll(token)
|
32
|
+
Authful::User[token].destroy
|
33
|
+
end
|
34
|
+
|
35
|
+
module Errors
|
36
|
+
class IncorrectApiToken < RuntimeError; end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
require_relative './authful/user'
|
41
|
+
require_relative './authful/response'
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Authful::User do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
Authful.configure do |c|
|
7
|
+
c.endpoint = "https://my-endpoint.dev/authful"
|
8
|
+
c.api_key = "my-awesome-api-key"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it "handles bad api key errors" do
|
13
|
+
FakeWeb.register_uri :post, "https://my-endpoint.dev/authful/api/users", {body: {error: "Incrorrect API token"}.to_json, status: ["401", "Unauthorized"]}
|
14
|
+
|
15
|
+
-> { Authful::User.create!(email: "john.doe@gmail.com", phone: "12055555434") }.should raise_error(Authful::Errors::IncorrectApiToken)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "creates a user" do
|
19
|
+
FakeWeb.register_uri :post, "https://my-endpoint.dev/authful/api/users", {body: {token: "user-authful-token", email: "john.doe@gmail.com", qr_code: "qr-code"}.to_json}
|
20
|
+
|
21
|
+
u = Authful::User.new(email: "john.doe@gmail.com", phone: "12055555434")
|
22
|
+
|
23
|
+
u.save.should eq('user-authful-token')
|
24
|
+
u.token.should eq('user-authful-token')
|
25
|
+
u.qr_code.should eq('qr-code')
|
26
|
+
u.error.should be_nil
|
27
|
+
end
|
28
|
+
|
29
|
+
it "accepts error on duplicate user, and finds user" do
|
30
|
+
FakeWeb.register_uri :post, "https://my-endpoint.dev/authful/api/users", {body: {error: "already enrolled", token: "user-authful-token"}.to_json, status: ["409", "Something"]}
|
31
|
+
|
32
|
+
u = Authful::User.new(email: "john.doe@gmail.com", phone: "12055555434")
|
33
|
+
|
34
|
+
u.save.should eq('user-authful-token')
|
35
|
+
u.token.should eq('user-authful-token')
|
36
|
+
u.error.should be_nil
|
37
|
+
end
|
38
|
+
|
39
|
+
it "errors on invalid user" do
|
40
|
+
FakeWeb.register_uri :post, "https://my-endpoint.dev/authful/api/users", {body: {error: "Invalid user, email is required."}.to_json, status: ["400", "Bad Request"]}
|
41
|
+
|
42
|
+
u = Authful::User.new(email: "", phone: "")
|
43
|
+
|
44
|
+
u.save.should eq(false)
|
45
|
+
u.error.should eq("Invalid user, email is required.")
|
46
|
+
end
|
47
|
+
|
48
|
+
it "validates the users token" do
|
49
|
+
FakeWeb.register_uri :get, "https://my-endpoint.dev/authful/api/users/user-authful-token/validate?token=000000", {body: {ok: 1}.to_json}
|
50
|
+
|
51
|
+
u = Authful::User["user-authful-token"]
|
52
|
+
u.valid?("000000").should eq(true)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "does not validate invalid tokens" do
|
56
|
+
FakeWeb.register_uri :get, "https://my-endpoint.dev/authful/api/users/user-authful-token/validate?token=000000", {body: {error: "Invalid token"}.to_json, status: [403, "Forbidden"]}
|
57
|
+
|
58
|
+
u = Authful::User["user-authful-token"]
|
59
|
+
u.valid?("000000").should eq(false)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "sends sms to users" do
|
63
|
+
FakeWeb.register_uri :get, "https://my-endpoint.dev/authful/api/users/user-authful-token/send_sms", {body: {ok: 1}.to_json}
|
64
|
+
|
65
|
+
u = Authful::User["user-authful-token"]
|
66
|
+
u.send_sms.should eq(true)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "catches failed sms" do
|
70
|
+
FakeWeb.register_uri :get, "https://my-endpoint.dev/authful/api/users/user-authful-token/send_sms", {body: {error: "It just didn't send"}.to_json, status: [400, "Bad Request"]}
|
71
|
+
|
72
|
+
u = Authful::User["user-authful-token"]
|
73
|
+
u.send_sms.should eq(false)
|
74
|
+
u.error = "It just didn't send"
|
75
|
+
end
|
76
|
+
|
77
|
+
it "deletes users" do
|
78
|
+
FakeWeb.register_uri :delete, "https://my-endpoint.dev/authful/api/users/user-authful-token", {body: {ok: 1}.to_json}
|
79
|
+
|
80
|
+
u = Authful::User["user-authful-token"]
|
81
|
+
u.destroy.should eq(true)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "accepts the wrapper function for enroll" do
|
85
|
+
FakeWeb.register_uri :post, "https://my-endpoint.dev/authful/api/users", {body: {token: "user-authful-token", email: "john.doe@gmail.com", qr_code: "qr-code"}.to_json}
|
86
|
+
|
87
|
+
r = Authful.enroll("john.doe@gmail.com", "12055555434")
|
88
|
+
|
89
|
+
r.token.should eq('user-authful-token')
|
90
|
+
r.qr_code.should eq('qr-code')
|
91
|
+
r.error.should be_nil
|
92
|
+
end
|
93
|
+
|
94
|
+
it "accepts the wrapper function for validating the users token" do
|
95
|
+
FakeWeb.register_uri :get, "https://my-endpoint.dev/authful/api/users/user-authful-token/validate?token=000000", {body: {ok: 1}.to_json}
|
96
|
+
|
97
|
+
Authful.validate("user-authful-token", "000000").should eq(true)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "accepts the wrapper function for send sms" do
|
101
|
+
FakeWeb.register_uri :get, "https://my-endpoint.dev/authful/api/users/user-authful-token/send_sms", {body: {ok: 1}.to_json}
|
102
|
+
|
103
|
+
Authful.send_sms("user-authful-token").should eq(true)
|
104
|
+
end
|
105
|
+
|
106
|
+
it "accepts the wrapper function for unenroll" do
|
107
|
+
FakeWeb.register_uri :delete, "https://my-endpoint.dev/authful/api/users/user-authful-token", {body: {ok: 1}.to_json}
|
108
|
+
|
109
|
+
Authful.unenroll("user-authful-token").should eq(true)
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: authful
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Chris Winslett
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-01-02 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rest-client
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: bundler
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '1.3'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '1.3'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: guard-rspec
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: guard-bundler
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: fakeweb
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: pry-debugger
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
description: A wrapper for the Authful service
|
127
|
+
email:
|
128
|
+
- chris@mongohq.com
|
129
|
+
executables: []
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files: []
|
132
|
+
files:
|
133
|
+
- .gitignore
|
134
|
+
- Gemfile
|
135
|
+
- Guardfile
|
136
|
+
- LICENSE.txt
|
137
|
+
- README.md
|
138
|
+
- Rakefile
|
139
|
+
- authful.gemspec
|
140
|
+
- lib/authful.rb
|
141
|
+
- lib/authful/response.rb
|
142
|
+
- lib/authful/user.rb
|
143
|
+
- lib/authful/version.rb
|
144
|
+
- spec/lib/authful/user_spec.rb
|
145
|
+
- spec/spec_helper.rb
|
146
|
+
homepage: ''
|
147
|
+
licenses:
|
148
|
+
- MIT
|
149
|
+
post_install_message:
|
150
|
+
rdoc_options: []
|
151
|
+
require_paths:
|
152
|
+
- lib
|
153
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
154
|
+
none: false
|
155
|
+
requirements:
|
156
|
+
- - ! '>='
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
159
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
160
|
+
none: false
|
161
|
+
requirements:
|
162
|
+
- - ! '>='
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '0'
|
165
|
+
requirements: []
|
166
|
+
rubyforge_project:
|
167
|
+
rubygems_version: 1.8.23
|
168
|
+
signing_key:
|
169
|
+
specification_version: 3
|
170
|
+
summary: Both authful is an open source tool that enables rapid implementation of
|
171
|
+
2fa for your application. This is the client for the service.
|
172
|
+
test_files:
|
173
|
+
- spec/lib/authful/user_spec.rb
|
174
|
+
- spec/spec_helper.rb
|