virgil-jwt 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,110 @@
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
+ # Represents content of [Jwt]
38
+ class JwtBodyContent
39
+ IDENTITY_PREFIX = 'identity-'.freeze
40
+ SUBJECT_PREFIX = 'virgil-'.freeze
41
+
42
+ # Jwt application id.
43
+ # @return [String]
44
+ attr_reader :app_id
45
+
46
+ # Jwt identity.
47
+ # @return [String]
48
+ attr_reader :identity
49
+
50
+ # Jwt issuer.
51
+ # @return [String]
52
+ attr_reader :issuer
53
+
54
+ # Jwt subject.
55
+ # @return [String]
56
+ attr_reader :subject
57
+
58
+ # When Jwt was issued.
59
+ # @return [Time]
60
+ attr_reader :issued_at
61
+
62
+ # When Jwt will expire.
63
+ # @return [Time]
64
+ attr_reader :expires_at
65
+
66
+ # Jwt additional data.
67
+ # @return [Hash]
68
+ attr_reader :additional_data
69
+
70
+ # Initializes a new instance of the class
71
+ # @param app_id [String] Application ID. Take it from {https://dashboard.virgilsecurity.com}
72
+ # @param identity [String] identity (must be equal to RawSignedModel identity when publishing card)
73
+ # @param issued_at [Time] issued data
74
+ # @param expires_at [Time] expiration date
75
+ # @param data [Hash] hash with additional data
76
+ def initialize(app_id:, identity:, issued_at:, expires_at:, data:)
77
+ @app_id = app_id
78
+ @identity = identity
79
+ @issued_at = issued_at
80
+ @expires_at = expires_at
81
+ @additional_data = data
82
+ @issuer = "#{SUBJECT_PREFIX}#{@app_id}"
83
+ @subject = "#{IDENTITY_PREFIX}#{@identity}"
84
+ end
85
+
86
+ # Json representation of body content
87
+ # @return [String]
88
+ def to_json
89
+ model = {
90
+ 'iss': issuer,
91
+ 'sub': subject,
92
+ 'iat': issued_at.to_i,
93
+ 'exp': expires_at.to_i,
94
+ 'ada': additional_data}
95
+ model.to_json
96
+ end
97
+
98
+ # Restore body content from json
99
+ # @return [JwtBodyContent]
100
+ def self.restore_from_json(str_json)
101
+ model = JSON.parse(str_json)
102
+ new(app_id: model['iss'].gsub(JwtBodyContent::SUBJECT_PREFIX, ''),
103
+ identity: model['sub'].gsub(JwtBodyContent::IDENTITY_PREFIX, ''),
104
+ issued_at: Time.at(model['iat']).utc,
105
+ expires_at: Time.at(model['exp']).utc,
106
+ data: model['ada'])
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,110 @@
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
+ class JwtGenerator
38
+
39
+ # Private Key which will be used for signing
40
+ # generated access tokens.
41
+ # Take it on {https://dashboard.virgilsecurity.com/api-keys}
42
+ # @return [PrivateKey]
43
+ attr_reader :api_key
44
+
45
+ # Key id of #api_key
46
+ # Take it on {https://dashboard.virgilsecurity.com/api-keys}
47
+ # @return [String]
48
+ attr_reader :api_public_key_id
49
+
50
+ # Application id
51
+ # Take it on {https://dashboard.virgilsecurity.com}
52
+ # @return [String]
53
+ attr_reader :app_id
54
+
55
+ # Lifetime of generated tokens in minutes
56
+ # @return [Integer]
57
+ attr_reader :life_time
58
+
59
+ # An instance of [AccessTokenSigner] that is used to
60
+ # generate token signature using #api_key
61
+ # @return [AccessTokenSigner]
62
+ attr_reader :access_token_signer
63
+
64
+ # Initializes a new instance of the class
65
+ # @param app_id [String] Application id
66
+ # Take it on {https://dashboard.virgilsecurity.com}
67
+ # @param api_key [PrivateKey] Private Key which will be used for signing
68
+ # generated access tokens. Take it on {https://dashboard.virgilsecurity.com/api-keys}
69
+ # @param api_public_key_id [String] Key id of #api_key.
70
+ # Take it on {https://dashboard.virgilsecurity.com/api-keys}
71
+ # @param life_time [Integer] Lifetime of generated tokens in minutes
72
+ # @param access_token_signer [AccessTokenSigner] An instance of [AccessTokenSigner]
73
+ # that is used to generate token signature using #api_key
74
+ def initialize(app_id:, api_key:, api_public_key_id:, life_time:, access_token_signer:)
75
+ @app_id = app_id
76
+ @api_key = api_key
77
+ @api_public_key_id = api_public_key_id
78
+ @life_time = life_time
79
+ @access_token_signer = access_token_signer
80
+ end
81
+
82
+ # Generates new JWT using specified identity and additional data.
83
+ # @param identity [String] identity to generate with.
84
+ # @param data [Hash] dictionary with additional data which will be kept in jwt body
85
+ # @return new instance of [Jwt]
86
+ def generate_token(identity, data = nil)
87
+ raise ArgumentError, 'Identity property is mandatory' if identity.nil?
88
+ issued_at = Time.now.utc
89
+ expires_at = Time.at(issued_at.to_i + @life_time * 60).utc
90
+ jwt_body = JwtBodyContent.new(app_id: @app_id,
91
+ issued_at: issued_at,
92
+ identity: identity,
93
+ expires_at: expires_at,
94
+ data: data)
95
+
96
+ jwt_header = JwtHeaderContent.new(algorithm: @access_token_signer.algorithm,
97
+ key_id: @api_public_key_id)
98
+ unsigned_jwt = Jwt.new(header_content: jwt_header,
99
+ body_content: jwt_body,
100
+ signature_data: nil)
101
+ jwt_bytes = Bytes.from_string(unsigned_jwt.to_s)
102
+ signature = @access_token_signer.generate_token_signature(jwt_bytes, @api_key)
103
+ Jwt.new(header_content: jwt_header,
104
+ body_content: jwt_body,
105
+ signature_data: signature)
106
+ end
107
+
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,94 @@
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
+ # Represents header of [Jwt]
38
+ class JwtHeaderContent
39
+ VIRGIL_CONTENT_TYPE = 'virgil-jwt;v=1'.freeze
40
+ JWT_TYPE = 'JWT'.freeze
41
+
42
+ # Signature algorithm
43
+ # @return [String]
44
+ attr_reader :algorithm
45
+
46
+ # Access token type.
47
+ # @return [String]
48
+ attr_reader :type
49
+
50
+ # Access token content type.
51
+ # @return [String]
52
+ attr_reader :content_type
53
+
54
+ # Id of public key which is used for jwt signature verification.
55
+ # @return [String]
56
+ attr_reader :key_id
57
+
58
+ # Initializes a new instance of the class
59
+ # @param algorithm [String] signature algorithm
60
+ # @param type [String] access token type
61
+ # @param content_type [String] Access token content type
62
+ # @param key_id [String] API key id. Take it from {https://dashboard.virgilsecurity.com/api-keys}
63
+ def initialize(algorithm:, key_id:, type: JWT_TYPE, content_type: VIRGIL_CONTENT_TYPE)
64
+ # todo validate
65
+ @algorithm = algorithm
66
+ @key_id = key_id
67
+ @type = type
68
+ @content_type = content_type
69
+ end
70
+
71
+ # Json representation of header content
72
+ # @return [String]
73
+ def to_json
74
+ model = {
75
+ 'alg': algorithm,
76
+ 'kid': key_id,
77
+ 'typ': type,
78
+ 'cty': content_type
79
+ }
80
+ model.to_json
81
+ end
82
+
83
+ # Restore header content from json
84
+ # @return [JwtHeaderContent]
85
+ def self.restore_from_json(str_json)
86
+ model = JSON.parse(str_json)
87
+ new(algorithm: model['alg'],
88
+ key_id: model['kid'],
89
+ type: model['typ'],
90
+ content_type: model['cty'])
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,78 @@
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
+ class JwtVerifier
38
+
39
+ # @return [AccessTokenSigner] that is used to
40
+ # verify token signature.
41
+ attr_reader :access_token_signer
42
+
43
+ # Public Key which should be used to verify signatures
44
+ # @return [PublicKey]
45
+ attr_reader :api_public_key
46
+
47
+ # Id of public key which should be used to verify signatures
48
+ # @return [String]
49
+ attr_reader :api_public_key_id
50
+
51
+ # Initializes a new instance of the class
52
+ # @param access_token_signer [AccessTokenSigner]
53
+ # @param api_public_key [PublicKey]
54
+ # @param api_public_key_id [String]
55
+ def initialize(access_token_signer:, api_public_key:, api_public_key_id:)
56
+ @access_token_signer = access_token_signer
57
+ @api_public_key = api_public_key
58
+ @api_public_key_id = api_public_key_id
59
+ end
60
+
61
+ # Verifies specified token.
62
+ # @param jwt [Jwt] token to be virefied.
63
+ # @return true if token is verified, otherwise false.
64
+ def verify_token(jwt)
65
+ if jwt.header_content.key_id != @api_public_key_id ||
66
+ jwt.header_content.algorithm != @access_token_signer.algorithm ||
67
+ jwt.header_content.content_type != JwtHeaderContent::VIRGIL_CONTENT_TYPE ||
68
+ jwt.header_content.type != JwtHeaderContent::JWT_TYPE
69
+ return false
70
+ end
71
+
72
+ @access_token_signer.verify_token_signature(jwt.signature_data,
73
+ jwt.unsigned_data,
74
+ api_public_key)
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,72 @@
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
+
38
+ # Provides payload for access token providers
39
+ class TokenContext
40
+
41
+ # Operation for which token is needed.
42
+ # @return [String]
43
+ attr_reader :operation
44
+
45
+ # Identity that should be used in access token.
46
+ # @return [String]
47
+ attr_reader :identity
48
+
49
+ # Service for which token is needed.
50
+ # @return [String]
51
+ attr_reader :service
52
+
53
+ # You can set up token cache in {CallbackJwtProvider#obtain_access_token_proc}
54
+ # and reset cached token if True.
55
+ # @return [TrueClass] or [FalseClass]
56
+ attr_reader :force_reload
57
+
58
+ # Initializes a new instance of the class
59
+ # @param operation [String] Operation for which token is needed
60
+ # @param identity [String] Identity to use in token
61
+ # @param force_reload [TrueClass] or [FalseClass]
62
+ # If you set up token cache in {CallbackJwtProvider#obtain_access_token_proc}
63
+ # it should reset cached token and return new if TRUE.
64
+ def initialize(operation:, identity:, service: nil, force_reload: false)
65
+ @operation = operation
66
+ @identity = identity
67
+ @service = service
68
+ @force_reload = force_reload
69
+ end
70
+ end
71
+ end
72
+ end