okta-jwt 0.3.0 → 0.4.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/Gemfile.lock +1 -1
- data/README.md +18 -12
- data/lib/okta/jwt.rb +21 -11
- data/lib/okta/jwt/version.rb +1 -1
- data/okta-jwt.gemspec +2 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c34b0de2f8f7061f57dfd025d6edf9451c1d072d0389df51a2661759df804f5
|
4
|
+
data.tar.gz: 6836b11074b80434ff5783cffba88df4a04a135a15baddddf471a20d82b6474c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c15287638cec9e58442dab0145820a7fb81d342d0f3591879346ed2a8a56b1ecea44f84283b181bc32e2888dc508b2ed7e10706c2f032aca7278a356b5154d3
|
7
|
+
data.tar.gz: a03afb95109f37b38a1f4b5ec0fbb1b1b44e9b73d1eaca2bd2582d586bd652fdb17e6e932132e462f3c863a6b2114b3e5fd0901da980bad93b52aa57cdb82964
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Okta::Jwt
|
2
2
|
|
3
|
-
Verify Okta JWT tokens using cached JWKs.
|
3
|
+
Verify Okta JWT access tokens using cached JWKs.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -25,28 +25,34 @@ Configure the client to sign in user (optional):
|
|
25
25
|
```ruby
|
26
26
|
# client for resource owner password flow
|
27
27
|
Okta::Jwt.configure_client!(
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
slogger: Logger.new(STDOUT) # optional
|
28
|
+
issuer: 'https://<org>.oktapreview.com/oauth2<auth_server_id>,
|
29
|
+
client_id: 'client_id,
|
30
|
+
client_secret: 'client_secret,
|
31
|
+
logger: Logger.new(STDOUT) # optional
|
33
32
|
)
|
34
33
|
```
|
35
34
|
|
36
|
-
Sign in user to get
|
35
|
+
Sign in user to get access token (default scope is openid):
|
37
36
|
|
38
37
|
```ruby
|
39
|
-
auth_response = Okta::Jwt.sign_in(
|
38
|
+
auth_response = Okta::Jwt.sign_in(
|
39
|
+
username: 'user@example.org',
|
40
|
+
password: 'password',
|
41
|
+
scope: 'openid my_scope'
|
42
|
+
)
|
40
43
|
parsed_auth_response = JSON.parse(auth_response.body)
|
44
|
+
access_token = parsed_auth_response['id_token']
|
41
45
|
```
|
42
46
|
|
43
|
-
Verify
|
47
|
+
Verify access token:
|
44
48
|
|
45
49
|
```ruby
|
46
|
-
|
47
|
-
|
50
|
+
verified_access_token = Okta::Jwt.verify_token(access_token,
|
51
|
+
issuer: 'https://<org>.oktapreview.com/oauth2<auth_server_id>,
|
52
|
+
audience: 'http://localhost:3000,
|
53
|
+
client_id: 'client_id'
|
54
|
+
)
|
48
55
|
```
|
49
|
-
NOTE: tokens are validated using data from header and payload: kid, iss and cid/aud. If you are just verifying the tokens there is no need to store anything at the client side.
|
50
56
|
|
51
57
|
## Development
|
52
58
|
|
data/lib/okta/jwt.rb
CHANGED
@@ -8,22 +8,24 @@ module Okta
|
|
8
8
|
module Jwt
|
9
9
|
module_function
|
10
10
|
|
11
|
+
class InvalidToken < Exception; end
|
12
|
+
|
11
13
|
# keys are cached under their kid value
|
12
14
|
JWKS_CACHE = {}
|
13
15
|
|
14
16
|
class << self
|
15
|
-
attr_accessor :
|
17
|
+
attr_accessor :issuer, :auth_server_id, :client_id, :client_secret, :public_key_ttl, :client, :logger
|
16
18
|
end
|
17
19
|
|
18
20
|
# configure the client for signing in
|
19
|
-
def configure_client!(
|
20
|
-
@
|
21
|
-
@auth_server_id = auth_server_id
|
21
|
+
def configure_client!(issuer:, client_id:, client_secret:, logger: Logger.new(IO::NULL))
|
22
|
+
@issuer = issuer
|
22
23
|
@client_id = client_id
|
23
24
|
@client_secret = client_secret
|
24
25
|
@logger = logger
|
25
|
-
|
26
|
-
|
26
|
+
@auth_server_id = issuer.split('/').last
|
27
|
+
|
28
|
+
@client = Faraday.new(url: issuer) do |f|
|
27
29
|
f.use Faraday::Adapter::NetHttp
|
28
30
|
f.headers['Accept'] = 'application/json'
|
29
31
|
end
|
@@ -40,14 +42,22 @@ module Okta
|
|
40
42
|
end
|
41
43
|
|
42
44
|
# validate the token
|
43
|
-
def verify_token(token)
|
44
|
-
|
45
|
+
def verify_token(token, issuer:, audience:, client_id:)
|
46
|
+
header, payload = token.split('.').first(2).map{|encoded| JSON.parse(Base64.decode64(encoded))}
|
47
|
+
|
48
|
+
# validate claims
|
49
|
+
raise InvalidToken.new('Invalid issuer') if payload['iss'] != issuer
|
50
|
+
raise InvalidToken.new('Invalid audience') if payload['aud'] != audience
|
51
|
+
raise InvalidToken.new('Invalid client') if payload['cid'] != client_id
|
52
|
+
raise InvalidToken.new('Token is expired') if payload['exp'].to_i <= Time.now.to_i
|
53
|
+
|
54
|
+
# validate signature
|
55
|
+
jwk = JSON::JWK.new(get_jwk(header, payload))
|
45
56
|
JSON::JWT.decode(token, jwk.to_key)
|
46
57
|
end
|
47
58
|
|
48
59
|
# extract public key from metadata's jwks_uri using kid
|
49
|
-
def get_jwk(
|
50
|
-
header, payload = token.split('.').first(2).map{|encoded| JSON.parse(Base64.decode64(encoded))}
|
60
|
+
def get_jwk(header, payload)
|
51
61
|
|
52
62
|
kid = header['kid']
|
53
63
|
return JWKS_CACHE[kid] if JWKS_CACHE[kid] # cache hit
|
@@ -67,7 +77,7 @@ module Okta
|
|
67
77
|
# fetch client metadata using cid/aud
|
68
78
|
def get_metadata(payload)
|
69
79
|
auth_server_id = payload['iss'].split('/').last # iss: "https://<org>.oktapreview.com/oauth2/<auth_server_id>"
|
70
|
-
client_id = payload['cid']
|
80
|
+
client_id = payload['cid']
|
71
81
|
|
72
82
|
client = Faraday.new(url: payload['iss']) do |f|
|
73
83
|
f.use Faraday::Adapter::NetHttp
|
data/lib/okta/jwt/version.rb
CHANGED
data/okta-jwt.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Damir Roso"]
|
10
10
|
spec.email = ["damir.roso@nih.gov"]
|
11
11
|
|
12
|
-
spec.summary = "Okta JWT
|
13
|
-
spec.description = "Okta JWT
|
12
|
+
spec.summary = "Verify Okta JWT access tokens using cached JWKs"
|
13
|
+
spec.description = "Verify Okta JWT access tokens using cached JWKs"
|
14
14
|
spec.homepage = "https://github.com/damir/okta-jwt"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: okta-jwt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Damir Roso
|
@@ -80,7 +80,7 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
-
description: Okta JWT
|
83
|
+
description: Verify Okta JWT access tokens using cached JWKs
|
84
84
|
email:
|
85
85
|
- damir.roso@nih.gov
|
86
86
|
executables: []
|
@@ -124,5 +124,5 @@ rubyforge_project:
|
|
124
124
|
rubygems_version: 2.7.6
|
125
125
|
signing_key:
|
126
126
|
specification_version: 4
|
127
|
-
summary: Okta JWT
|
127
|
+
summary: Verify Okta JWT access tokens using cached JWKs
|
128
128
|
test_files: []
|