http-token-auth 0.0.1 → 0.1.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.
- checksums.yaml +4 -4
- data/lib/http/token_auth.rb +4 -1
- data/lib/http/token_auth/authorization_header_parser.rb +13 -28
- data/lib/http/token_auth/challenge.rb +69 -0
- data/lib/http/token_auth/credentials.rb +24 -14
- data/lib/http/token_auth/scheme_parser.rb +29 -0
- data/lib/http/token_auth/version.rb +1 -1
- data/lib/http/token_auth/www_authenticate_header_parser.rb +47 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd2be20131fcf205b737d8b3e39b564b6e56447b
|
4
|
+
data.tar.gz: af2a0ac666a211d7db09279521e9a778b48eca38
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bc9b3e2db21a82004f0a219103791a50d4c91e1cc28d08703be1d590e7f324d6759ad83c44f49e13d5a4041db3d0d53a2e6381e1dc7ff5d4e0f413e2b9b8fb90
|
7
|
+
data.tar.gz: 7048ecff80de8c6f70ccfcb87eafccee714a39663afeea4fce1eaf4be17a1d65ebf77c82c618e4d1930fe5009259923c3841afd7f83d66d581d69e471d8cc08b
|
data/lib/http/token_auth.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'http/token_auth/version'
|
1
2
|
require 'http/token_auth/credentials'
|
3
|
+
require 'http/token_auth/challenge'
|
4
|
+
require 'http/token_auth/scheme_parser'
|
2
5
|
require 'http/token_auth/authorization_header_parser'
|
3
|
-
require 'http/token_auth/
|
6
|
+
require 'http/token_auth/www_authenticate_header_parser'
|
@@ -6,31 +6,15 @@ module HTTP
|
|
6
6
|
end
|
7
7
|
|
8
8
|
class AuthorizationHeaderParsingError < StandardError
|
9
|
-
def initialize(submessage)
|
10
|
-
super(%(Error parsing "Authorization" HTTP header with token scheme: #{submessage}))
|
11
|
-
end
|
12
9
|
end
|
13
10
|
|
14
11
|
class AuthorizationHeaderParser
|
15
|
-
def
|
16
|
-
|
17
|
-
raise AuthorizationHeaderParsingError,
|
18
|
-
'Header has no attributes' if attributes.nil?
|
19
|
-
raise AuthorizationHeaderParsingError,
|
20
|
-
%(Invalid scheme "#{scheme}") unless scheme == 'Token'
|
21
|
-
build_credentials parse_attributes(attributes)
|
22
|
-
end
|
23
|
-
|
24
|
-
def split(header)
|
25
|
-
header.split(' ', 2)
|
12
|
+
def initialize
|
13
|
+
@scheme_parser = SchemeParser.new
|
26
14
|
end
|
27
15
|
|
28
|
-
def
|
29
|
-
|
30
|
-
string.scan(/(\w+)="([^"]*)"/).each do |group|
|
31
|
-
attributes[group[0].to_sym] = group[1]
|
32
|
-
end
|
33
|
-
attributes
|
16
|
+
def parse(header)
|
17
|
+
build_credentials @scheme_parser.parse(header)
|
34
18
|
end
|
35
19
|
|
36
20
|
def build_credentials(attributes)
|
@@ -39,22 +23,23 @@ module HTTP
|
|
39
23
|
nonce: attributes[:nonce],
|
40
24
|
auth: attributes[:auth],
|
41
25
|
timestamp: parse_timestamp(attributes[:timestamp])
|
42
|
-
rescue
|
26
|
+
rescue CredentialsArgumentError => e
|
43
27
|
raise AuthorizationHeaderParsingError, e.message
|
44
28
|
end
|
45
29
|
|
46
|
-
def parse_coverage(
|
47
|
-
|
48
|
-
|
49
|
-
when '
|
30
|
+
def parse_coverage(string)
|
31
|
+
case string
|
32
|
+
when nil
|
33
|
+
when ''
|
34
|
+
when 'none' then :none
|
50
35
|
when 'base' then :base
|
51
36
|
when 'base+body-sha-256' then :base_body_sha_256
|
52
|
-
else raise AuthorizationHeaderParsingError, %(
|
37
|
+
else raise AuthorizationHeaderParsingError, %(Unsupported coverage "#{string}")
|
53
38
|
end
|
54
39
|
end
|
55
40
|
|
56
|
-
def parse_timestamp(
|
57
|
-
|
41
|
+
def parse_timestamp(string)
|
42
|
+
string.nil? ? nil : string.to_i
|
58
43
|
end
|
59
44
|
end
|
60
45
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module HTTP
|
2
|
+
module TokenAuth
|
3
|
+
class ChallengeArgumentError < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
class Challenge
|
7
|
+
attr_reader :realm, :supported_coverages, :timestamp
|
8
|
+
|
9
|
+
def initialize(realm:, supported_coverages: nil, timestamp: nil)
|
10
|
+
@realm = realm
|
11
|
+
@supported_coverages = supported_coverages_or_default(supported_coverages)
|
12
|
+
@timestamp = timestamp
|
13
|
+
validate_itself
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_header
|
17
|
+
attributes = []
|
18
|
+
attributes << %(realm="#{@realm}")
|
19
|
+
attributes << %(coverage="#{coverage_string}")
|
20
|
+
unless supported_coverages.include?(:none)
|
21
|
+
attributes << %(timestamp="#{@timestamp}")
|
22
|
+
end
|
23
|
+
"Token #{attributes.join(', ')}"
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def supported_coverages_or_default(list)
|
29
|
+
return [:base] if list.nil? || list.empty?
|
30
|
+
list
|
31
|
+
end
|
32
|
+
|
33
|
+
def validate_itself
|
34
|
+
must_have_realm
|
35
|
+
supported_coverages_must_be_consistent
|
36
|
+
must_have_timestamp unless supported_coverages.include?(:none)
|
37
|
+
end
|
38
|
+
|
39
|
+
def must_have_realm
|
40
|
+
raise ChallengeArgumentError, '"realm" is missing' if @realm.nil? || @realm.empty?
|
41
|
+
end
|
42
|
+
|
43
|
+
def must_have_timestamp
|
44
|
+
raise ChallengeArgumentError, '"timestamp" is missing' if @timestamp.nil?
|
45
|
+
end
|
46
|
+
|
47
|
+
def supported_coverages_must_be_consistent
|
48
|
+
if supported_coverages.include?(:none) && supported_coverages.size > 1
|
49
|
+
raise ChallengeArgumentError,
|
50
|
+
'coverage "none" cannot be combined with other coverages'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def coverage_string
|
55
|
+
@supported_coverages.map do |coverage|
|
56
|
+
coverage_name(coverage)
|
57
|
+
end.join(' ')
|
58
|
+
end
|
59
|
+
|
60
|
+
def coverage_name(coverage)
|
61
|
+
case coverage
|
62
|
+
when :none then 'none'
|
63
|
+
when :base then 'base'
|
64
|
+
when :base_body_sha_256 then 'base+body-sha-256'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -1,9 +1,6 @@
|
|
1
1
|
module HTTP
|
2
2
|
module TokenAuth
|
3
|
-
class
|
4
|
-
def initialize(argument_name)
|
5
|
-
super(%(Invalid token credentials: "#{argument_name}" is missing))
|
6
|
-
end
|
3
|
+
class CredentialsArgumentError < StandardError
|
7
4
|
end
|
8
5
|
|
9
6
|
class Credentials
|
@@ -11,7 +8,7 @@ module HTTP
|
|
11
8
|
|
12
9
|
def initialize(token:, coverage: nil, nonce: nil, auth: nil, timestamp: nil)
|
13
10
|
@token = token
|
14
|
-
@coverage = coverage
|
11
|
+
@coverage = coverage.nil? ? :none : coverage
|
15
12
|
@nonce = nonce
|
16
13
|
@auth = auth
|
17
14
|
@timestamp = timestamp
|
@@ -21,7 +18,7 @@ module HTTP
|
|
21
18
|
def to_header
|
22
19
|
attributes = []
|
23
20
|
attributes << %(token="#{@token}")
|
24
|
-
unless coverage
|
21
|
+
unless coverage == :none
|
25
22
|
attributes << %(coverage="#{coverage_name}")
|
26
23
|
attributes << %(nonce="#{@nonce}")
|
27
24
|
attributes << %(auth="#{@auth}")
|
@@ -34,26 +31,39 @@ module HTTP
|
|
34
31
|
|
35
32
|
def validate_itself
|
36
33
|
must_have_token
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
34
|
+
must_have_valid_coverage
|
35
|
+
unless @coverage == :none
|
36
|
+
must_have_nonce
|
37
|
+
must_have_auth
|
38
|
+
must_have_timestamp
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def must_have_valid_coverage
|
43
|
+
case @coverage
|
44
|
+
when :none
|
45
|
+
when :base
|
46
|
+
when :base_body_sha_256
|
47
|
+
return
|
48
|
+
else
|
49
|
+
raise CredentialsArgumentError, %(unsupported "#{@coverage}" coverage)
|
50
|
+
end
|
41
51
|
end
|
42
52
|
|
43
53
|
def must_have_token
|
44
|
-
raise
|
54
|
+
raise CredentialsArgumentError, '"token" is missing' if @token.nil? || @token.empty?
|
45
55
|
end
|
46
56
|
|
47
57
|
def must_have_nonce
|
48
|
-
raise
|
58
|
+
raise CredentialsArgumentError, '"nonce" is missing' if @nonce.nil? || @nonce.empty?
|
49
59
|
end
|
50
60
|
|
51
61
|
def must_have_auth
|
52
|
-
raise
|
62
|
+
raise CredentialsArgumentError, '"auth" is missing' if @auth.nil? || @auth.empty?
|
53
63
|
end
|
54
64
|
|
55
65
|
def must_have_timestamp
|
56
|
-
raise
|
66
|
+
raise CredentialsArgumentError, '"timestamp" is missing' if @timestamp.nil?
|
57
67
|
end
|
58
68
|
|
59
69
|
def coverage_name
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module HTTP
|
2
|
+
module TokenAuth
|
3
|
+
class SchemeParsingError < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
class SchemeParser
|
7
|
+
def parse(string)
|
8
|
+
scheme, attributes_string = split(string)
|
9
|
+
raise SchemeParsingError,
|
10
|
+
'No attributes provided' if attributes_string.nil?
|
11
|
+
raise SchemeParsingError,
|
12
|
+
%(Unsupported scheme "#{scheme}") unless scheme == 'Token'
|
13
|
+
parse_attributes(attributes_string)
|
14
|
+
end
|
15
|
+
|
16
|
+
def split(string)
|
17
|
+
string.split(' ', 2)
|
18
|
+
end
|
19
|
+
|
20
|
+
def parse_attributes(string)
|
21
|
+
attributes = {}
|
22
|
+
string.scan(/(\w+)="([^"]*)"/).each do |group|
|
23
|
+
attributes[group[0].to_sym] = group[1]
|
24
|
+
end
|
25
|
+
attributes
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module HTTP
|
2
|
+
module TokenAuth
|
3
|
+
def self.parse_www_authenticate_header(header)
|
4
|
+
parser = WWWAuthenticateHeaderParser.new
|
5
|
+
parser.parse(header)
|
6
|
+
end
|
7
|
+
|
8
|
+
class WWWAuthenticateHeaderParsingError < StandardError
|
9
|
+
end
|
10
|
+
|
11
|
+
class WWWAuthenticateHeaderParser
|
12
|
+
def initialize
|
13
|
+
@schema_parser = SchemeParser.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def parse(header)
|
17
|
+
build_challenge @schema_parser.parse(header)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def build_challenge(attributes)
|
23
|
+
Challenge.new realm: attributes[:realm],
|
24
|
+
supported_coverages: parse_coverage(attributes[:coverage]),
|
25
|
+
timestamp: parse_timestamp(attributes[:timestamp])
|
26
|
+
rescue ChallengeArgumentError => e
|
27
|
+
raise WWWAuthenticateHeaderParsingError, e.message
|
28
|
+
end
|
29
|
+
|
30
|
+
def parse_coverage(string)
|
31
|
+
return [:base] if string.nil?
|
32
|
+
string.split.map do |token|
|
33
|
+
case token
|
34
|
+
when 'none' then :none
|
35
|
+
when 'base' then :base
|
36
|
+
when 'base+body-sha-256' then :base_body_sha_256
|
37
|
+
else raise WWWAuthenticateHeaderParsingError, %(Unsupported coverage "#{token}")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def parse_timestamp(string)
|
43
|
+
string.nil? ? nil : string.to_i
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: http-token-auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Felipe Dornelas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-03-
|
11
|
+
date: 2016-03-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -49,8 +49,11 @@ files:
|
|
49
49
|
- http-token-auth.gemspec
|
50
50
|
- lib/http/token_auth.rb
|
51
51
|
- lib/http/token_auth/authorization_header_parser.rb
|
52
|
+
- lib/http/token_auth/challenge.rb
|
52
53
|
- lib/http/token_auth/credentials.rb
|
54
|
+
- lib/http/token_auth/scheme_parser.rb
|
53
55
|
- lib/http/token_auth/version.rb
|
56
|
+
- lib/http/token_auth/www_authenticate_header_parser.rb
|
54
57
|
homepage: https://github.com/felipead/http-token-auth
|
55
58
|
licenses:
|
56
59
|
- MIT
|
@@ -71,7 +74,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
74
|
version: '0'
|
72
75
|
requirements: []
|
73
76
|
rubyforge_project:
|
74
|
-
rubygems_version: 2.4.5
|
77
|
+
rubygems_version: 2.4.5.1
|
75
78
|
signing_key:
|
76
79
|
specification_version: 4
|
77
80
|
summary: Ruby gem to handle the HTTP Token Access Authentication.
|