signed_api 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +48 -0
- data/Rakefile +1 -0
- data/lib/signed_api.rb +110 -0
- data/lib/signed_api/version.rb +3 -0
- data/signed_api.gemspec +24 -0
- data/spec/signed_api_spec.rb +105 -0
- data/spec/spec_helper.rb +1 -0
- metadata +101 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 417c51a567e81d9aa1947d5b449390fb8485954b
|
|
4
|
+
data.tar.gz: ac5806bd0571ec2fcab13a968f4c4917ee347dff
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 7a8abf9335e3adf9e102e0ca505c9643962318f76abfa4d920f84b182c18ce98c44f241235943c79968af787cbb02b15285f7ee3a5fb574ea6dd7674addf014a
|
|
7
|
+
data.tar.gz: 67a134983ee25e04458927b0ffb6c0c373df4607cca18c90de2fbd8f5ea92b960a1cc1a2223ca3eadb840d1f22996608db03c2bc1dd9d70ffd48887799fca1f6
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2015 ykmr1224
|
|
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,48 @@
|
|
|
1
|
+
# SignedApi
|
|
2
|
+
|
|
3
|
+
SignedApi gem offers easy way to make your web APIs secure by using secret key based signature authentication.
|
|
4
|
+
This uses the similar way as AWS's signed URLs.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
Add this line to your application's Gemfile:
|
|
9
|
+
|
|
10
|
+
gem 'signed_api'
|
|
11
|
+
|
|
12
|
+
And then execute:
|
|
13
|
+
|
|
14
|
+
$ bundle
|
|
15
|
+
|
|
16
|
+
Or install it yourself as:
|
|
17
|
+
|
|
18
|
+
$ gem install signed_api
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### Client side
|
|
23
|
+
You can easily sign your params by sign_params method
|
|
24
|
+
```ruby
|
|
25
|
+
signed_params = SignedApi::sign_params('GET', '/api/search', {a: 'param_a', b: 'param_b', c: 'param_c'}, 'SOME_KEY', 'SOME_SECRET_STRING', 60)
|
|
26
|
+
```
|
|
27
|
+
or you can directly make a signed URL like this.
|
|
28
|
+
```ruby
|
|
29
|
+
signed_url = SignedApi::get_signed_url('https://example.com', 'GET', '/api/search', {a: 'param_a', b: 'param_b', c: 'param_c'}, 'SOME_KEY', 'SOME_SECRET_STRING', 60)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Server side
|
|
33
|
+
You can verify the request easily.
|
|
34
|
+
```ruby
|
|
35
|
+
begin
|
|
36
|
+
SignedApi::verify_signature!(method, path, params) {|key| secrets[key]}
|
|
37
|
+
rescue
|
|
38
|
+
# log error and return error to the client
|
|
39
|
+
end
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Contributing
|
|
43
|
+
|
|
44
|
+
1. Fork it
|
|
45
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
46
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
47
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
48
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
data/lib/signed_api.rb
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
require "signed_api/version"
|
|
2
|
+
require 'openssl'
|
|
3
|
+
require 'uri'
|
|
4
|
+
require 'cgi'
|
|
5
|
+
require 'base64'
|
|
6
|
+
|
|
7
|
+
module SignedApi
|
|
8
|
+
extend self
|
|
9
|
+
|
|
10
|
+
class MissingParameterError < RuntimeError; end
|
|
11
|
+
class AuthSecretNotFoundError < RuntimeError; end
|
|
12
|
+
class SignatureExpiredError < RuntimeError; end
|
|
13
|
+
class SignatureUnmatchError < RuntimeError; end
|
|
14
|
+
|
|
15
|
+
# Returns url signed by the key, secret, and expiry
|
|
16
|
+
#
|
|
17
|
+
# Parameter examples
|
|
18
|
+
# root_url : "http://example.com"
|
|
19
|
+
# method : "GET"/"POST"/etc
|
|
20
|
+
# path : "/some/useful/api"
|
|
21
|
+
# params : {:param1 => "value1", :param2 => "value2"}
|
|
22
|
+
# key : "SomeKeyStringForYourSecretKey"
|
|
23
|
+
# secret : "anysecretstring"
|
|
24
|
+
# expiry_limit : 60 #the signature will be expired in 60 sec
|
|
25
|
+
def get_signed_url(root_url, method, path, params, key, secret, expiry_limit=60)
|
|
26
|
+
params = ApiHelper::sign_params(method, path, params, key, secret, expiry_limit)
|
|
27
|
+
root_url + path + '?' + ApiHelper::normalize_params(params)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def get_signed_path(method, path, params, key, secret, expiry_limit=60)
|
|
31
|
+
params = ApiHelper::sign_params(method, path, params, key, secret, expiry_limit)
|
|
32
|
+
path + '?' + ApiHelper::normalize_params(params)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Returns signature added parameter hash
|
|
36
|
+
#
|
|
37
|
+
# method: HTTP METHOD ('GET', 'POST', etc)
|
|
38
|
+
# path: invoked path ('/api/search', '/api/get', etc)
|
|
39
|
+
# params: http params ({param1: value1, param2: value2}, etc)
|
|
40
|
+
# key: authentication key (any string)
|
|
41
|
+
# secret: authentication secret (any string)
|
|
42
|
+
# expiry_limit: the request will expire in expiry_limit seconds (integer)
|
|
43
|
+
def sign_params(method, path, params, key, secret, expiry_limit=60)
|
|
44
|
+
raise ArgumentError, "Expected string for method parameter" unless method.kind_of?(String)
|
|
45
|
+
raise ArgumentError, "Expected string for path parameter" unless path.kind_of?(String)
|
|
46
|
+
raise ArgumentError, "Expected hash for params parameter" unless params.kind_of?(Hash)
|
|
47
|
+
raise ArgumentError, "Expected string for key parameter" unless key.kind_of?(String)
|
|
48
|
+
raise ArgumentError, "Expected string for secret parameter" unless secret.kind_of?(String)
|
|
49
|
+
raise ArgumentError, "Expected integer for expiry_limit parameter" unless expiry_limit.kind_of?(Integer)
|
|
50
|
+
raise ArgumentError, "Expected params not contain auth_key/auth_hash/expiry" unless params[:auth_key].nil? && params[:auth_hash].nil? && params[:expiry].nil?
|
|
51
|
+
res_params = params.merge(auth_key: key, expiry: (Time.now.utc.to_i + expiry_limit).to_s)
|
|
52
|
+
string_to_sign = signed_string(method, path, res_params)
|
|
53
|
+
res_params[:auth_hash] = sha256_hmac_base64(secret, string_to_sign)
|
|
54
|
+
return res_params
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Verify input params contains valid signature
|
|
58
|
+
#
|
|
59
|
+
# This method will raise an error if the verification failed.
|
|
60
|
+
def verify_signature!(method, path, params, &get_secret)
|
|
61
|
+
auth_hash = params[:auth_hash]
|
|
62
|
+
|
|
63
|
+
# duplicate params without :auth_hash
|
|
64
|
+
params = params.reject{|key| key==:auth_hash}
|
|
65
|
+
auth_key = params[:auth_key]
|
|
66
|
+
expiry = params[:expiry]
|
|
67
|
+
raise MissingParameterError, "auth_key, auth_hash, or expiry is missing" if auth_key.nil? || auth_hash.nil? || expiry.nil?
|
|
68
|
+
|
|
69
|
+
secret = get_secret.call(auth_key)
|
|
70
|
+
raise AuthSecretNotFoundError, "auth_secret for the auth_key is not found" if secret.nil?
|
|
71
|
+
|
|
72
|
+
now = Time.now.utc.to_i.to_s
|
|
73
|
+
raise SignatureExpiredError if now > expiry
|
|
74
|
+
|
|
75
|
+
raise SignatureUnmatchError, "auth_hash did not match" if auth_hash != gen_authhash(method, path, params, auth_key, secret)
|
|
76
|
+
|
|
77
|
+
return true
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Verify input params contain valid signature
|
|
81
|
+
#
|
|
82
|
+
# This method merely returns the result of verification by true or false.
|
|
83
|
+
def verify_signature(method, path, params, &get_secret)
|
|
84
|
+
begin
|
|
85
|
+
return true if verify_signature!(method, path, params, &get_secret)
|
|
86
|
+
rescue MissingParameterError, AuthSecretNotFoundError, SignatureExpiredError, SignatureUnmatchError
|
|
87
|
+
return false
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def normalize_params(params)
|
|
92
|
+
params.collect{|key, value| "#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s)}"}.compact.sort! * "&"
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
protected
|
|
96
|
+
|
|
97
|
+
def signed_string(method, path, params)
|
|
98
|
+
"#{method}\n#{path}\n#{normalize_params(params)}"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def sha256_hmac_base64(secret, string_to_sign)
|
|
102
|
+
digest = OpenSSL::Digest::SHA256.new
|
|
103
|
+
Base64.strict_encode64(OpenSSL::HMAC.digest(digest, secret, string_to_sign))
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def gen_authhash(method, path, params, key, secret)
|
|
107
|
+
string_to_sign = signed_string(method, path, params)
|
|
108
|
+
sha256_hmac_base64(secret, string_to_sign)
|
|
109
|
+
end
|
|
110
|
+
end
|
data/signed_api.gemspec
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'signed_api/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = "signed_api"
|
|
8
|
+
spec.version = SignedApi::VERSION
|
|
9
|
+
spec.authors = ["ykmr1224"]
|
|
10
|
+
spec.email = ["ykmr1224@gmail.com"]
|
|
11
|
+
spec.description = %q{SignedApi gem offers easy way to make your web APIs secure by using secret key based signature authentication.}
|
|
12
|
+
spec.summary = %q{SignedApi gem offers easy way to make your web APIs secure by using secret key based signature authentication.}
|
|
13
|
+
spec.homepage = "https://github.com/ykmr1224"
|
|
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_development_dependency "bundler", "~> 1.3"
|
|
22
|
+
spec.add_development_dependency "rake"
|
|
23
|
+
spec.add_development_dependency "rspec"
|
|
24
|
+
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'signed_api'
|
|
3
|
+
|
|
4
|
+
describe SignedApi do
|
|
5
|
+
it 'should have a version number' do
|
|
6
|
+
expect(SignedApi::VERSION).not_to be_nil
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
describe "#sign_params" do
|
|
10
|
+
it "signs parameter properly" do
|
|
11
|
+
params = SignedApi::sign_params("GET", "/api/search", {a: "param_a", b: "param_b", c: "param_c"}, "key", "secret", 10)
|
|
12
|
+
expect(params[:auth_key]).to eql("key")
|
|
13
|
+
expect(params[:auth_hash]).not_to be_nil
|
|
14
|
+
expect(params[:expiry]).not_to be_nil
|
|
15
|
+
expect(params[:expiry].to_i).to be > Time.now.utc.to_i
|
|
16
|
+
expect(params[:expiry].to_i).to be < Time.now.utc.to_i+20
|
|
17
|
+
expect(params[:a]).to eql("param_a")
|
|
18
|
+
expect(params[:b]).to eql("param_b")
|
|
19
|
+
expect(params[:c]).to eql("param_c")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "handle exceptional case properly" do
|
|
23
|
+
expect {
|
|
24
|
+
SignedApi::sign_params(nil, "/api/search", {a: "param_a"}, "key", "secret", 10)
|
|
25
|
+
}.to raise_error
|
|
26
|
+
|
|
27
|
+
expect {
|
|
28
|
+
SignedApi::sign_params('GET', nil, {a: "param_a"}, "key", "secret", 10)
|
|
29
|
+
}.to raise_error
|
|
30
|
+
|
|
31
|
+
expect {
|
|
32
|
+
SignedApi::sign_params('GET', "/api/search", nil, "key", "secret", 10)
|
|
33
|
+
}.to raise_error
|
|
34
|
+
|
|
35
|
+
expect {
|
|
36
|
+
SignedApi::sign_params('GET', "/api/search", {a: "param_a"}, nil, "secret", 10)
|
|
37
|
+
}.to raise_error
|
|
38
|
+
|
|
39
|
+
expect {
|
|
40
|
+
SignedApi::sign_params('GET', "/api/search", {a: "param_a"}, "key", nil, 10)
|
|
41
|
+
}.to raise_error
|
|
42
|
+
|
|
43
|
+
expect {
|
|
44
|
+
SignedApi::sign_params('GET', "/api/search", {a: "param_a"}, "key", "secret", "10")
|
|
45
|
+
}.to raise_error
|
|
46
|
+
|
|
47
|
+
expect {
|
|
48
|
+
SignedApi::sign_params('GET', "/api/search", {a: "param_a", auth_key: "hoge"}, "key", "secret", 10)
|
|
49
|
+
}.to raise_error
|
|
50
|
+
|
|
51
|
+
expect {
|
|
52
|
+
SignedApi::sign_params('GET', "/api/search", {a: "param_a", auth_hash: "hoge"}, "key", "secret", 10)
|
|
53
|
+
}.to raise_error
|
|
54
|
+
|
|
55
|
+
expect {
|
|
56
|
+
SignedApi::sign_params('GET', "/api/search", {a: "param_a", expiry: "hoge"}, "key", "secret", 10)
|
|
57
|
+
}.to raise_error
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
describe "#verify_signature!" do
|
|
62
|
+
it "verify properly" do
|
|
63
|
+
params = SignedApi::sign_params("POST", "/api/find", {a: "param_a", b: "param_b", c: "param_c"}, "key", "secret", 10)
|
|
64
|
+
expect(SignedApi::verify_signature!("POST", "/api/find", params){|key| "secret"}).to be true
|
|
65
|
+
|
|
66
|
+
key = "123456789ABCDEF"
|
|
67
|
+
secret = "123456789ABCDEF0123456789ABCDEF0"
|
|
68
|
+
params = SignedApi::sign_params("GET", "/", {a: "param_a", b: "param_b", c: "param_c"}, key, secret, 10)
|
|
69
|
+
expect(SignedApi::verify_signature!("GET", "/", params){|key| secret}).to be true
|
|
70
|
+
|
|
71
|
+
params = SignedApi::sign_params("GET", "/", {}, key, secret, 10)
|
|
72
|
+
expect(SignedApi::verify_signature!("GET", "/", params){|key| secret}).to be true
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "reject properly" do
|
|
76
|
+
params = SignedApi::sign_params("POST", "/api/find", {a: "param_a", b: "param_b", c: "param_c"}, "key", "secret", 30)
|
|
77
|
+
expect{ SignedApi::verify_signature!("GET", "/api/find", params){|key| "secret"} }.to raise_error(SignedApi::SignatureUnmatchError)
|
|
78
|
+
expect{ SignedApi::verify_signature!("POST", "/api/finds", params){|key| "secret"} }.to raise_error(SignedApi::SignatureUnmatchError)
|
|
79
|
+
expect{ SignedApi::verify_signature!("POST", "api/find", params){|key| "secret"} }.to raise_error(SignedApi::SignatureUnmatchError)
|
|
80
|
+
expect{ SignedApi::verify_signature!("POST", "/api/find", params){|key| "wrongsecret"} }.to raise_error(SignedApi::SignatureUnmatchError)
|
|
81
|
+
expect{ SignedApi::verify_signature!("POST", "/api/find", params){|key| ""} }.to raise_error(SignedApi::SignatureUnmatchError)
|
|
82
|
+
params[:a] = "param_"
|
|
83
|
+
expect{ SignedApi::verify_signature!("POST", "/api/find", params){|key| ""} }.to raise_error(SignedApi::SignatureUnmatchError)
|
|
84
|
+
params[:a] = "param_a"
|
|
85
|
+
params[:x] = "param_x"
|
|
86
|
+
expect{ SignedApi::verify_signature!("POST", "/api/find", params){|key| ""} }.to raise_error(SignedApi::SignatureUnmatchError)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it "handle exceptional case properly" do
|
|
90
|
+
params = SignedApi::sign_params("POST", "/api/find", {a: "param_a", b: "param_b", c: "param_c"}, "key", "secret", 10)
|
|
91
|
+
expect{ SignedApi::verify_signature!("POST", "", params){|key| nil} }.to raise_error(SignedApi::AuthSecretNotFoundError)
|
|
92
|
+
|
|
93
|
+
expect{ SignedApi::verify_signature!("POST", "", params.reject{|k| k==:auth_key}){|key| "secret"} }.to raise_error(SignedApi::MissingParameterError)
|
|
94
|
+
expect{ SignedApi::verify_signature!("POST", "", params.reject{|k| k==:auth_hash}){|key| "secret"} }.to raise_error(SignedApi::MissingParameterError)
|
|
95
|
+
expect{ SignedApi::verify_signature!("POST", "", params.reject{|k| k==:expiry}){|key| "secret"} }.to raise_error(SignedApi::MissingParameterError)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "reject expired signature" do
|
|
99
|
+
params = SignedApi::sign_params("POST", "/api/find", {a: "param_a", b: "param_b", c: "param_c"}, "key", "secret", 0)
|
|
100
|
+
sleep 1
|
|
101
|
+
expect{ SignedApi::verify_signature!("POST", "/api/find", params){|key| "secret"} }.to raise_error(SignedApi::SignatureExpiredError)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
end
|
|
105
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'rubygems'
|
metadata
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: signed_api
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- ykmr1224
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2015-06-21 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: bundler
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ~>
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.3'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ~>
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.3'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - '>='
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - '>='
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rspec
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - '>='
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - '>='
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
description: SignedApi gem offers easy way to make your web APIs secure by using secret
|
|
56
|
+
key based signature authentication.
|
|
57
|
+
email:
|
|
58
|
+
- ykmr1224@gmail.com
|
|
59
|
+
executables: []
|
|
60
|
+
extensions: []
|
|
61
|
+
extra_rdoc_files: []
|
|
62
|
+
files:
|
|
63
|
+
- .gitignore
|
|
64
|
+
- Gemfile
|
|
65
|
+
- LICENSE.txt
|
|
66
|
+
- README.md
|
|
67
|
+
- Rakefile
|
|
68
|
+
- lib/signed_api.rb
|
|
69
|
+
- lib/signed_api/version.rb
|
|
70
|
+
- signed_api.gemspec
|
|
71
|
+
- spec/signed_api_spec.rb
|
|
72
|
+
- spec/spec_helper.rb
|
|
73
|
+
homepage: https://github.com/ykmr1224
|
|
74
|
+
licenses:
|
|
75
|
+
- MIT
|
|
76
|
+
metadata: {}
|
|
77
|
+
post_install_message:
|
|
78
|
+
rdoc_options: []
|
|
79
|
+
require_paths:
|
|
80
|
+
- lib
|
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
82
|
+
requirements:
|
|
83
|
+
- - '>='
|
|
84
|
+
- !ruby/object:Gem::Version
|
|
85
|
+
version: '0'
|
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
87
|
+
requirements:
|
|
88
|
+
- - '>='
|
|
89
|
+
- !ruby/object:Gem::Version
|
|
90
|
+
version: '0'
|
|
91
|
+
requirements: []
|
|
92
|
+
rubyforge_project:
|
|
93
|
+
rubygems_version: 2.4.5
|
|
94
|
+
signing_key:
|
|
95
|
+
specification_version: 4
|
|
96
|
+
summary: SignedApi gem offers easy way to make your web APIs secure by using secret
|
|
97
|
+
key based signature authentication.
|
|
98
|
+
test_files:
|
|
99
|
+
- spec/signed_api_spec.rb
|
|
100
|
+
- spec/spec_helper.rb
|
|
101
|
+
has_rdoc:
|