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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c36ef2a88c57081ef6bcc849ed38d9748a5ecde2e22ca97736f450279ae7c06d
4
- data.tar.gz: 33d2250564526da5d3fa3afad60b64938445bd7af8b8114d63d4df2d03e02cbc
3
+ metadata.gz: 8c34b0de2f8f7061f57dfd025d6edf9451c1d072d0389df51a2661759df804f5
4
+ data.tar.gz: 6836b11074b80434ff5783cffba88df4a04a135a15baddddf471a20d82b6474c
5
5
  SHA512:
6
- metadata.gz: 7076073b437641283faf8636a55e043852892ab63ca34687969ca8b09e27445978cdef92907dddbc469194fbdec8239eb45d9055e39bf543e6221e89634bc742
7
- data.tar.gz: b7a62844e4ec132db22b68188896e38546336a2e89f51471f96657120b361d0c7eba6e71a00d9fcf71beec8d42d2fa8133bc540176ab7ddbcf1e4ee6dd80014b
6
+ metadata.gz: 8c15287638cec9e58442dab0145820a7fb81d342d0f3591879346ed2a8a56b1ecea44f84283b181bc32e2888dc508b2ed7e10706c2f032aca7278a356b5154d3
7
+ data.tar.gz: a03afb95109f37b38a1f4b5ec0fbb1b1b44e9b73d1eaca2bd2582d586bd652fdb17e6e932132e462f3c863a6b2114b3e5fd0901da980bad93b52aa57cdb82964
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- okta-jwt (0.3.0)
4
+ okta-jwt (0.4.0)
5
5
  faraday
6
6
  json-jwt
7
7
 
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
- issuer_url: 'https://organization.oktapreview.com,
29
- auth_server_id: 'auth_server_id,
30
- client_id: 'client_id,
31
- client_secret: 'client_secret,
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 tokens (default scope is openid):
35
+ Sign in user to get access token (default scope is openid):
37
36
 
38
37
  ```ruby
39
- auth_response = Okta::Jwt.sign_in(username: 'user@example.org', password: 'password', scope: 'openid my_scope')
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 tokens:
47
+ Verify access token:
44
48
 
45
49
  ```ruby
46
- verified_id_token = Okta::Jwt.verify_token(parsed_auth_response['id_token'])
47
- verified_access_token = Okta::Jwt.verify_token(parsed_auth_response['access_token'])
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
 
@@ -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 :issuer_url, :auth_server_id, :client_id, :client_secret, :public_key_ttl, :client, :logger
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!(issuer_url:, auth_server_id:, client_id:, client_secret:, logger: Logger.new(IO::NULL))
20
- @issuer_url = issuer_url
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
- @client = Faraday.new(url: issuer_url) do |f|
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
- jwk = JSON::JWK.new(get_jwk(token))
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(token)
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'] || payload['aud'] # id_token has client_id value under aud key
80
+ client_id = payload['cid']
71
81
 
72
82
  client = Faraday.new(url: payload['iss']) do |f|
73
83
  f.use Faraday::Adapter::NetHttp
@@ -1,5 +1,5 @@
1
1
  module Okta
2
2
  module Jwt
3
- VERSION = "0.3.0"
3
+ VERSION = "0.4.0"
4
4
  end
5
5
  end
@@ -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 verifier"
13
- spec.description = "Okta JWT verifier"
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.3.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 verifier
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 verifier
127
+ summary: Verify Okta JWT access tokens using cached JWKs
128
128
  test_files: []