okta-jwt 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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: []