Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
ecommerce
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
ecommerce
Commits
e7aba82b
Commit
e7aba82b
authored
May 17, 2016
by
Clinton Blackburn
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #740 from edx/clintonb/multiple-signers
Updated JWT decode handler to support multiple signing keys
parents
5f0f8f07
b3a613b9
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
102 additions
and
23 deletions
+102
-23
ecommerce/extensions/api/handlers.py
+27
-19
ecommerce/extensions/api/tests/test_handlers.py
+71
-0
ecommerce/settings/base.py
+4
-4
No files found.
ecommerce/extensions/api/handlers.py
View file @
e7aba82b
...
@@ -29,22 +29,30 @@ def jwt_decode_handler(token):
...
@@ -29,22 +29,30 @@ def jwt_decode_handler(token):
# JWT_ISSUERS is not one of DRF-JWT's default settings, and cannot be accessed
# JWT_ISSUERS is not one of DRF-JWT's default settings, and cannot be accessed
# using the `api_settings` object without overriding DRF-JWT's defaults.
# using the `api_settings` object without overriding DRF-JWT's defaults.
issuers
=
settings
.
JWT_AUTH
[
'JWT_ISSUERS'
]
issuers
=
settings
.
JWT_AUTH
[
'JWT_ISSUERS'
]
for
issuer
in
issuers
:
secret_keys
=
settings
.
JWT_AUTH
[
'JWT_SECRET_KEYS'
]
or
(
api_settings
.
JWT_SECRET_KEY
,)
try
:
return
jwt
.
decode
(
# TODO (CCB): The usage of multiple issuers complicates matters. We should only have one issuer.
token
,
# Update ecommerce-worker to properly use client credentials, and remove the internal loop. (ECOM-4477)
api_settings
.
JWT_SECRET_KEY
,
for
secret_key
in
secret_keys
:
api_settings
.
JWT_VERIFY
,
for
issuer
in
issuers
:
options
=
options
,
try
:
leeway
=
api_settings
.
JWT_LEEWAY
,
return
jwt
.
decode
(
audience
=
api_settings
.
JWT_AUDIENCE
,
token
,
issuer
=
issuer
,
secret_key
,
algorithms
=
[
api_settings
.
JWT_ALGORITHM
]
api_settings
.
JWT_VERIFY
,
)
options
=
options
,
except
jwt
.
InvalidIssuerError
:
leeway
=
api_settings
.
JWT_LEEWAY
,
pass
audience
=
api_settings
.
JWT_AUDIENCE
,
except
jwt
.
InvalidTokenError
:
issuer
=
issuer
,
logger
.
exception
(
'JWT decode failed!'
)
algorithms
=
[
api_settings
.
JWT_ALGORITHM
]
raise
)
except
jwt
.
InvalidIssuerError
:
raise
jwt
.
InvalidIssuerError
# Ignore these errors since we have multiple issuers
pass
except
jwt
.
DecodeError
:
# Ignore these errors since we have multiple signing keys
pass
except
jwt
.
InvalidTokenError
:
logger
.
exception
(
'JWT decode failed!'
)
raise
jwt
.
InvalidTokenError
(
'All combinations of JWT issuers and secret keys failed to validate the token.'
)
ecommerce/extensions/api/tests/test_handlers.py
0 → 100644
View file @
e7aba82b
""" Tests for handler functions. """
from
time
import
time
from
django.conf
import
settings
from
django.test
import
TestCase
import
jwt
import
mock
from
oscar.test.factories
import
UserFactory
from
ecommerce.extensions.api.handlers
import
jwt_decode_handler
ISSUERS
=
(
'test-issuer'
,
'another-issuer'
,)
SIGNING_KEYS
=
(
'insecure-secret-key'
,
'secret'
,
'another-secret'
,)
def
generate_jwt_token
(
payload
,
signing_key
=
None
):
"""Generate a valid JWT token for authenticated requests."""
signing_key
=
signing_key
or
settings
.
JWT_AUTH
[
'JWT_SECRET_KEY'
]
return
jwt
.
encode
(
payload
,
signing_key
)
.
decode
(
'utf-8'
)
def
generate_jwt_payload
(
user
):
"""Generate a valid JWT payload given a user."""
now
=
int
(
time
())
ttl
=
5
return
{
'iss'
:
settings
.
JWT_AUTH
[
'JWT_ISSUERS'
][
0
],
'username'
:
user
.
username
,
'email'
:
user
.
email
,
'iat'
:
now
,
'exp'
:
now
+
ttl
}
class
JWTDecodeHandlerTests
(
TestCase
):
""" Tests for the `jwt_decode_handler` utility function. """
def
setUp
(
self
):
super
(
JWTDecodeHandlerTests
,
self
)
.
setUp
()
self
.
user
=
UserFactory
()
self
.
payload
=
generate_jwt_payload
(
self
.
user
)
self
.
jwt
=
generate_jwt_token
(
self
.
payload
)
def
test_decode_success
(
self
):
self
.
assertEqual
(
jwt_decode_handler
(
self
.
jwt
),
self
.
payload
)
def
test_decode_success_with_multiple_issuers
(
self
):
settings
.
JWT_AUTH
[
'JWT_ISSUERS'
]
=
ISSUERS
for
issuer
in
ISSUERS
:
self
.
payload
[
'iss'
]
=
issuer
token
=
generate_jwt_token
(
self
.
payload
)
self
.
assertEqual
(
jwt_decode_handler
(
token
),
self
.
payload
)
def
test_decode_success_with_multiple_signing_keys
(
self
):
settings
.
JWT_AUTH
[
'JWT_SECRET_KEYS'
]
=
SIGNING_KEYS
for
signing_key
in
SIGNING_KEYS
:
token
=
generate_jwt_token
(
self
.
payload
,
signing_key
)
self
.
assertEqual
(
jwt_decode_handler
(
token
),
self
.
payload
)
def
test_decode_error
(
self
):
# Update the payload to ensure a validation error
self
.
payload
[
'exp'
]
=
0
token
=
generate_jwt_token
(
self
.
payload
)
with
mock
.
patch
(
'ecommerce.extensions.api.handlers.logger'
)
as
patched_log
:
with
self
.
assertRaises
(
jwt
.
InvalidTokenError
):
jwt_decode_handler
(
token
)
patched_log
.
exception
.
assert_called_once_with
(
'JWT decode failed!'
)
ecommerce/settings/base.py
View file @
e7aba82b
...
@@ -326,13 +326,13 @@ JWT_AUTH = {
...
@@ -326,13 +326,13 @@ JWT_AUTH = {
'JWT_SECRET_KEY'
:
None
,
'JWT_SECRET_KEY'
:
None
,
'JWT_ALGORITHM'
:
'HS256'
,
'JWT_ALGORITHM'
:
'HS256'
,
'JWT_VERIFY_EXPIRATION'
:
True
,
'JWT_VERIFY_EXPIRATION'
:
True
,
# NOTE (CCB): This is temporarily set to False until we decide what values
# are acceptable.
'JWT_VERIFY_AUDIENCE'
:
False
,
'JWT_LEEWAY'
:
1
,
'JWT_LEEWAY'
:
1
,
'JWT_DECODE_HANDLER'
:
'ecommerce.extensions.api.handlers.jwt_decode_handler'
,
'JWT_DECODE_HANDLER'
:
'ecommerce.extensions.api.handlers.jwt_decode_handler'
,
# Th
is setting is not one
of DRF-JWT's defaults.
# Th
ese settings are NOT part
of DRF-JWT's defaults.
'JWT_ISSUERS'
:
(),
'JWT_ISSUERS'
:
(),
# NOTE (CCB): This is temporarily set to False until we decide what values are acceptable.
'JWT_VERIFY_AUDIENCE'
:
False
,
'JWT_SECRET_KEYS'
:
(),
}
}
# Service user for worker processes.
# Service user for worker processes.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment