virgil-jwt 1.0.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 +7 -0
- data/.gitignore +10 -0
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +37 -0
- data/LICENSE.txt +33 -0
- data/README.md +203 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/virgil-sdk-ruby-jwt +3 -0
- data/lib/virgil/jwt.rb +14 -0
- data/lib/virgil/jwt/access_token.rb +51 -0
- data/lib/virgil/jwt/access_token_provider.rb +46 -0
- data/lib/virgil/jwt/bytes.rb +125 -0
- data/lib/virgil/jwt/caching_jwt_provider.rb +74 -0
- data/lib/virgil/jwt/callback_jwt_provider.rb +60 -0
- data/lib/virgil/jwt/const_access_token_provider.rb +56 -0
- data/lib/virgil/jwt/jwt.rb +132 -0
- data/lib/virgil/jwt/jwt_body_content.rb +110 -0
- data/lib/virgil/jwt/jwt_generator.rb +110 -0
- data/lib/virgil/jwt/jwt_header_content.rb +94 -0
- data/lib/virgil/jwt/jwt_verifier.rb +78 -0
- data/lib/virgil/jwt/token_context.rb +72 -0
- data/lib/virgil/jwt/validation.rb +59 -0
- data/lib/virgil/jwt/version.rb +5 -0
- data/virgil-jwt.gemspec +31 -0
- metadata +161 -0
@@ -0,0 +1,125 @@
|
|
1
|
+
# Copyright (C) 2015-2019 Virgil Security Inc.
|
2
|
+
#
|
3
|
+
# Lead Maintainer: Virgil Security Inc. <support@virgilsecurity.com>
|
4
|
+
#
|
5
|
+
# All rights reserved.
|
6
|
+
#
|
7
|
+
# Redistribution and use in source and binary forms, with or without
|
8
|
+
# modification, are permitted provided that the following conditions are
|
9
|
+
# met:
|
10
|
+
#
|
11
|
+
# (1) Redistributions of source code must retain the above copyright
|
12
|
+
# notice, this list of conditions and the following disclaimer.
|
13
|
+
#
|
14
|
+
# (2) Redistributions in binary form must reproduce the above copyright
|
15
|
+
# notice, this list of conditions and the following disclaimer in
|
16
|
+
# the documentation and/or other materials provided with the
|
17
|
+
# distribution.
|
18
|
+
#
|
19
|
+
# (3) Neither the name of the copyright holder nor the names of its
|
20
|
+
# contributors may be used to endorse or promote products derived from
|
21
|
+
# this software without specific prior written permission.
|
22
|
+
#
|
23
|
+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR
|
24
|
+
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
25
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
26
|
+
# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
27
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
28
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
29
|
+
# SERVICES; LOSS OF USE, bytes, OR PROFITS; OR BUSINESS INTERRUPTION)
|
30
|
+
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
31
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
32
|
+
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
33
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
34
|
+
|
35
|
+
require 'base64'
|
36
|
+
require 'json'
|
37
|
+
|
38
|
+
module Virgil
|
39
|
+
module Jwt
|
40
|
+
class Bytes < Array
|
41
|
+
# Initializes a new array of bytes from specified string, which encodes binary data.
|
42
|
+
# @param str [String] String to decode.
|
43
|
+
# @param encoding [VirgilStringEncoding] The character encoding of string.
|
44
|
+
# @raise [ArgumentError] if encoding is undefined
|
45
|
+
def self.from_string(str, encoding = VirgilStringEncoding::UTF8)
|
46
|
+
case encoding
|
47
|
+
when VirgilStringEncoding::BASE64
|
48
|
+
from_base64(str)
|
49
|
+
when VirgilStringEncoding::HEX
|
50
|
+
from_hex(str)
|
51
|
+
when VirgilStringEncoding::UTF8
|
52
|
+
from_utf8(str)
|
53
|
+
else
|
54
|
+
raise ArgumentError, 'Encoding is undefined'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Decodes the current bytes to a string according to the specified
|
59
|
+
# character encoding.
|
60
|
+
# @param encoding [VirgilStringEncoding] The character encoding to encode to.
|
61
|
+
# equivalent string representation if raw bytes in selected encoding.
|
62
|
+
# @return [String]
|
63
|
+
# @raise [ArgumentError] if encoding is undefined
|
64
|
+
def to_string(encoding = VirgilStringEncoding::UTF8)
|
65
|
+
case encoding
|
66
|
+
when VirgilStringEncoding::BASE64
|
67
|
+
to_base64
|
68
|
+
when VirgilStringEncoding::HEX
|
69
|
+
to_hex
|
70
|
+
when VirgilStringEncoding::UTF8
|
71
|
+
to_s
|
72
|
+
else
|
73
|
+
raise ArgumentError, 'Encoding is undefined'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Converts all the bytes to its equivalent string representation in utf8.
|
78
|
+
def to_s
|
79
|
+
pack('c*')
|
80
|
+
end
|
81
|
+
|
82
|
+
# Initializes a new array of bytes from specified string,
|
83
|
+
# which encodes binary data as base-64 digits.
|
84
|
+
def self.from_base64(str)
|
85
|
+
new(Base64.decode64(str).bytes)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Initializes a new array of bytes from specified string,
|
89
|
+
# which encodes binary data as utf8.
|
90
|
+
def self.from_utf8(str)
|
91
|
+
new(str.bytes)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Initializes a new array of bytes from specified string,
|
95
|
+
# which encodes binary data as hexadecimal digits.
|
96
|
+
def self.from_hex(str)
|
97
|
+
new(str.scan(/../).map { |x| x.hex })
|
98
|
+
end
|
99
|
+
|
100
|
+
# Converts all the bytes to its equivalent string representation that
|
101
|
+
# is encoded with base-64 digits.
|
102
|
+
def to_base64
|
103
|
+
Base64.strict_encode64(to_s)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Encodes all the bytes into a utf8 string.
|
107
|
+
def to_utf8
|
108
|
+
to_s
|
109
|
+
end
|
110
|
+
|
111
|
+
# Converts the numeric value of each element of a current array of bytes to its
|
112
|
+
# equivalent hexadecimal string representation.
|
113
|
+
def to_hex
|
114
|
+
to_s.each_byte.map { |b| b.to_s(16) }.join
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
module VirgilStringEncoding
|
120
|
+
BASE64 = 1
|
121
|
+
HEX = 2
|
122
|
+
UTF8 = 3
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# Copyright (C) 2015-2019 Virgil Security Inc.
|
2
|
+
#
|
3
|
+
# Lead Maintainer: Virgil Security Inc. <support@virgilsecurity.com>
|
4
|
+
#
|
5
|
+
# All rights reserved.
|
6
|
+
#
|
7
|
+
# Redistribution and use in source and binary forms, with or without
|
8
|
+
# modification, are permitted provided that the following conditions are
|
9
|
+
# met:
|
10
|
+
#
|
11
|
+
# (1) Redistributions of source code must retain the above copyright
|
12
|
+
# notice, this list of conditions and the following disclaimer.
|
13
|
+
#
|
14
|
+
# (2) Redistributions in binary form must reproduce the above copyright
|
15
|
+
# notice, this list of conditions and the following disclaimer in
|
16
|
+
# the documentation and/or other materials provided with the
|
17
|
+
# distribution.
|
18
|
+
#
|
19
|
+
# (3) Neither the name of the copyright holder nor the names of its
|
20
|
+
# contributors may be used to endorse or promote products derived from
|
21
|
+
# this software without specific prior written permission.
|
22
|
+
#
|
23
|
+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR
|
24
|
+
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
25
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
26
|
+
# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
27
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
28
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
29
|
+
# SERVICES; LOSS OF USE, bytes, OR PROFITS; OR BUSINESS INTERRUPTION)
|
30
|
+
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
31
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
32
|
+
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
33
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
34
|
+
require 'thread'
|
35
|
+
|
36
|
+
module Virgil
|
37
|
+
module Jwt
|
38
|
+
|
39
|
+
# Provides an opportunity to
|
40
|
+
# get cached access token or renew it using callback mechanism.
|
41
|
+
class CachingJwtProvider < AccessTokenProvider
|
42
|
+
|
43
|
+
# Callback, that takes an instance of [TokenContext]
|
44
|
+
# and returns string representation of generated instance of [AccessToken]
|
45
|
+
# @return [Proc]
|
46
|
+
attr_reader :renew_access_token_proc
|
47
|
+
|
48
|
+
@@mutex = Mutex.new
|
49
|
+
def initialize(obtain_token_proc)
|
50
|
+
Validation.check_type_argument!(Proc, obtain_token_proc)
|
51
|
+
@renew_access_token_proc = obtain_token_proc
|
52
|
+
end
|
53
|
+
|
54
|
+
# Gets cached or renewed access token.
|
55
|
+
# @param token_context an instance of [TokenContext]
|
56
|
+
# @return The instance of [AccessToken]
|
57
|
+
def get_token(token_context)
|
58
|
+
Validation.check_type_argument!(TokenContext, token_context)
|
59
|
+
|
60
|
+
if !@jwt || (@jwt.body_content.expires_at <= Time.at(Time.now.utc.to_i + 5).utc)
|
61
|
+
@@mutex.synchronize {
|
62
|
+
jwt_str = @renew_access_token_proc.call(token_context)
|
63
|
+
@jwt = Jwt.from(jwt_str)
|
64
|
+
}
|
65
|
+
end
|
66
|
+
@jwt
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
attr_reader :jwt
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Copyright (C) 2015-2019 Virgil Security Inc.
|
2
|
+
#
|
3
|
+
# Lead Maintainer: Virgil Security Inc. <support@virgilsecurity.com>
|
4
|
+
#
|
5
|
+
# All rights reserved.
|
6
|
+
#
|
7
|
+
# Redistribution and use in source and binary forms, with or without
|
8
|
+
# modification, are permitted provided that the following conditions are
|
9
|
+
# met:
|
10
|
+
#
|
11
|
+
# (1) Redistributions of source code must retain the above copyright
|
12
|
+
# notice, this list of conditions and the following disclaimer.
|
13
|
+
#
|
14
|
+
# (2) Redistributions in binary form must reproduce the above copyright
|
15
|
+
# notice, this list of conditions and the following disclaimer in
|
16
|
+
# the documentation and/or other materials provided with the
|
17
|
+
# distribution.
|
18
|
+
#
|
19
|
+
# (3) Neither the name of the copyright holder nor the names of its
|
20
|
+
# contributors may be used to endorse or promote products derived from
|
21
|
+
# this software without specific prior written permission.
|
22
|
+
#
|
23
|
+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR
|
24
|
+
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
25
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
26
|
+
# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
27
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
28
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
29
|
+
# SERVICES; LOSS OF USE, bytes, OR PROFITS; OR BUSINESS INTERRUPTION)
|
30
|
+
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
31
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
32
|
+
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
33
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
34
|
+
|
35
|
+
module Virgil
|
36
|
+
module Jwt
|
37
|
+
# provides an opportunity to
|
38
|
+
# get access token using callback mechanism.
|
39
|
+
class CallbackJwtProvider < AccessTokenProvider
|
40
|
+
|
41
|
+
# Callback, that takes an instance of [TokenContext]
|
42
|
+
# and returns string representation of generated instance of [AccessToken]
|
43
|
+
attr_reader :obtain_access_token_proc
|
44
|
+
|
45
|
+
def initialize(obtain_token_proc)
|
46
|
+
Validation.check_type_argument!(Proc, obtain_token_proc)
|
47
|
+
@obtain_access_token_proc = obtain_token_proc
|
48
|
+
end
|
49
|
+
|
50
|
+
# Gets access token.
|
51
|
+
# @param token_context [TokenContext]
|
52
|
+
# @return [AccessToken] Access token
|
53
|
+
def get_token(token_context)
|
54
|
+
Validation.check_type_argument!(TokenContext, token_context)
|
55
|
+
jwt_str = @obtain_access_token_proc.call(token_context)
|
56
|
+
Jwt.from(jwt_str)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# Copyright (C) 2015-2019 Virgil Security Inc.
|
2
|
+
#
|
3
|
+
# Lead Maintainer: Virgil Security Inc. <support@virgilsecurity.com>
|
4
|
+
#
|
5
|
+
# All rights reserved.
|
6
|
+
#
|
7
|
+
# Redistribution and use in source and binary forms, with or without
|
8
|
+
# modification, are permitted provided that the following conditions are
|
9
|
+
# met:
|
10
|
+
#
|
11
|
+
# (1) Redistributions of source code must retain the above copyright
|
12
|
+
# notice, this list of conditions and the following disclaimer.
|
13
|
+
#
|
14
|
+
# (2) Redistributions in binary form must reproduce the above copyright
|
15
|
+
# notice, this list of conditions and the following disclaimer in
|
16
|
+
# the documentation and/or other materials provided with the
|
17
|
+
# distribution.
|
18
|
+
#
|
19
|
+
# (3) Neither the name of the copyright holder nor the names of its
|
20
|
+
# contributors may be used to endorse or promote products derived from
|
21
|
+
# this software without specific prior written permission.
|
22
|
+
#
|
23
|
+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR
|
24
|
+
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
25
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
26
|
+
# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
27
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
28
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
29
|
+
# SERVICES; LOSS OF USE, bytes, OR PROFITS; OR BUSINESS INTERRUPTION)
|
30
|
+
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
31
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
32
|
+
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
33
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
34
|
+
|
35
|
+
module Virgil
|
36
|
+
module Jwt
|
37
|
+
# Provides an opportunity to use constant access token.
|
38
|
+
class ConstAccessTokenProvider < AccessTokenProvider
|
39
|
+
def initialize(token)
|
40
|
+
@access_token = token
|
41
|
+
end
|
42
|
+
|
43
|
+
# Gets access token.
|
44
|
+
# @param token_context [TokenContext] can be null as
|
45
|
+
# it does not affect the result.
|
46
|
+
# @return [AccessToken]
|
47
|
+
def get_token(token_context)
|
48
|
+
access_token
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
attr_reader :access_token
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
# Copyright (C) 2015-2019 Virgil Security Inc.
|
2
|
+
#
|
3
|
+
# Lead Maintainer: Virgil Security Inc. <support@virgilsecurity.com>
|
4
|
+
#
|
5
|
+
# All rights reserved.
|
6
|
+
#
|
7
|
+
# Redistribution and use in source and binary forms, with or without
|
8
|
+
# modification, are permitted provided that the following conditions are
|
9
|
+
# met:
|
10
|
+
#
|
11
|
+
# (1) Redistributions of source code must retain the above copyright
|
12
|
+
# notice, this list of conditions and the following disclaimer.
|
13
|
+
#
|
14
|
+
# (2) Redistributions in binary form must reproduce the above copyright
|
15
|
+
# notice, this list of conditions and the following disclaimer in
|
16
|
+
# the documentation and/or other materials provided with the
|
17
|
+
# distribution.
|
18
|
+
#
|
19
|
+
# (3) Neither the name of the copyright holder nor the names of its
|
20
|
+
# contributors may be used to endorse or promote products derived from
|
21
|
+
# this software without specific prior written permission.
|
22
|
+
#
|
23
|
+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR
|
24
|
+
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
25
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
26
|
+
# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
27
|
+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
28
|
+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
29
|
+
# SERVICES; LOSS OF USE, bytes, OR PROFITS; OR BUSINESS INTERRUPTION)
|
30
|
+
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
31
|
+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
32
|
+
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
33
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
34
|
+
|
35
|
+
module Virgil
|
36
|
+
module Jwt
|
37
|
+
# Implements [AccessToken] in terms of Virgil JWT.
|
38
|
+
class Jwt < AccessToken
|
39
|
+
# Gets a jwt body
|
40
|
+
# @return [JwtBodyContent]
|
41
|
+
attr_reader :body_content
|
42
|
+
|
43
|
+
# Gets a jwt header
|
44
|
+
# @return [JwtHeaderContent]
|
45
|
+
attr_reader :header_content
|
46
|
+
|
47
|
+
# Gets a digital signature of jwt
|
48
|
+
# @return [Bytes]
|
49
|
+
attr_reader :signature_data
|
50
|
+
|
51
|
+
# String representation of jwt without signature.
|
52
|
+
# It equals to:
|
53
|
+
# Base64.urlsafe_encode64(JWT Header) + "." + Base64.urlsafe_encode64(JWT Body)
|
54
|
+
# @return [String]
|
55
|
+
attr_reader :unsigned_data
|
56
|
+
|
57
|
+
# Initializes a new instance of the [Jwt] class using specified header,
|
58
|
+
# body and signature.
|
59
|
+
# @param header_content [JwtHeaderContext] jwt header
|
60
|
+
# @param body_content [JwtBodyContent] jwt body
|
61
|
+
# @param signature_data [Bytes] jwt signature data
|
62
|
+
def initialize(header_content:, body_content:, signature_data:)
|
63
|
+
@header_content = header_content
|
64
|
+
@body_content = body_content
|
65
|
+
@signature_data = signature_data
|
66
|
+
@string_representation = "#{header_base64}.#{body_base64}"
|
67
|
+
@unsigned_data = Bytes.from_string(@string_representation)
|
68
|
+
@string_representation += ".#{signature_base64}" unless @signature_data.nil?
|
69
|
+
end
|
70
|
+
|
71
|
+
# Initializes a new instance of the [Jwt] class using
|
72
|
+
# its string representation
|
73
|
+
# @param jwt_str [String] string representation of signed jwt.
|
74
|
+
# It must be equal to:
|
75
|
+
# Base64.urlsafe_encode64(jwt_header.to_base64) + "."
|
76
|
+
# + Base64.urlsafe_encode64(JWT Body) "."
|
77
|
+
# + Base64.urlsafe_encode64(Jwt Signature).
|
78
|
+
# @return [Jwt]
|
79
|
+
def self.from(jwt_str)
|
80
|
+
begin
|
81
|
+
parts = jwt_str.split('.')
|
82
|
+
raise ArgumentError unless parts.size == 3
|
83
|
+
signature_data = Bytes.new(Base64.urlsafe_decode64(parts[2]).bytes)
|
84
|
+
new(header_content: parse_header_content(parts[0]),
|
85
|
+
body_content: parse_body_content(parts[1]),
|
86
|
+
signature_data: signature_data)
|
87
|
+
rescue StandardError
|
88
|
+
raise ArgumentError, 'Wrong JWT format.'
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
# String representation of jwt.
|
94
|
+
# @return [String]
|
95
|
+
def to_s
|
96
|
+
@string_representation
|
97
|
+
end
|
98
|
+
|
99
|
+
# Whether or not token is expired.
|
100
|
+
# @return [TrueClass]
|
101
|
+
def expired?
|
102
|
+
Time.now.utc >= @body_content.expires_at
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
attr_reader :string_representation
|
108
|
+
|
109
|
+
def self.parse_body_content(str)
|
110
|
+
body_json = Base64.urlsafe_decode64(str)
|
111
|
+
JwtBodyContent.restore_from_json(body_json)
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.parse_header_content(str)
|
115
|
+
header_json = Base64.urlsafe_decode64(str)
|
116
|
+
JwtHeaderContent.restore_from_json(header_json)
|
117
|
+
end
|
118
|
+
|
119
|
+
def header_base64
|
120
|
+
Base64.urlsafe_encode64(@header_content.to_json, padding: false)
|
121
|
+
end
|
122
|
+
|
123
|
+
def body_base64
|
124
|
+
Base64.urlsafe_encode64(@body_content.to_json, padding: false)
|
125
|
+
end
|
126
|
+
|
127
|
+
def signature_base64
|
128
|
+
Base64.urlsafe_encode64(@signature_data.to_s, padding: false)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|