http-token-auth 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|