-
Notifications
You must be signed in to change notification settings - Fork 107
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a0764f9
commit a7fe25d
Showing
14 changed files
with
479 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
pulp.app.auth | ||
================= | ||
|
||
.. automodule:: pulpcore.app.auth | ||
|
||
pulp.app.auth.jwt | ||
------------------------- | ||
|
||
.. automodule:: pulpcore.app.auth.jwt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ pulp.app | |
.. toctree:: | ||
|
||
apps | ||
auth | ||
fields | ||
models | ||
response | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
Authentication | ||
============== | ||
|
||
All calls to REST API endpoints must be authenticated as a particular User. | ||
|
||
.. tip:: | ||
The password for the "admin" user can be set using two methods. | ||
|
||
``pulp-manager reset-admin-password`` | ||
|
||
The above command prompts the user to enter a new password for "admin" user. | ||
|
||
``pulp-manager reset-admin-password --random`` | ||
|
||
The above command generates a random password for "admin" user and prints it to the screen. | ||
|
||
.. tip:: | ||
If you are using django rest framework browsable API these browser addons may come handy: | ||
|
||
* Chrome `ModHeader <https://chrome.google.com/webstore/detail/modheader/idgpnmonknjnojddfkpgkljpfnnfcklj>`_ | ||
* Firefox `Modify Headers <https://addons.mozilla.org/cs/firefox/addon/modify-headers/>`_ | ||
|
||
Basic Authentication | ||
-------------------- | ||
|
||
Any call to the REST API may use | ||
`HTTP basic authentication <http://tools.ietf.org/html/rfc1945#section-11.1>`_ to provide | ||
a username and password. | ||
|
||
JWT Authentication | ||
------------------ | ||
|
||
Alternatively you can use `JSON Web Tokens authentication <https://tools.ietf.org/html/rfc7519>`_. | ||
|
||
Token Structure | ||
^^^^^^^^^^^^^^^ | ||
|
||
The structure of the token consists of ``username`` and ``exp``. The tokens are signed by each | ||
user's individual secret by HMAC SHA-256 ("HS256") algorithm. | ||
|
||
Example: | ||
:: | ||
{ | ||
"username": "admin", | ||
"exp": 1501172472 | ||
} | ||
|
||
Obtaining token from server | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
You can "login" to Pulp by supplying your credentials in POST request and obtain a JWT token | ||
with expiration time set by ``JWT_AUTH.JWT_EXPIRATION_DELTA`` | ||
|
||
|
||
* **method:** ``post`` | ||
* **path:** ``api/v3/jwt/`` | ||
* response list: | ||
* **code:** ``200`` - credentials were accepted | ||
* **code:** ``400`` - credentials are wrong | ||
|
||
**Sample POST request:** | ||
:: | ||
{ | ||
"username": "admin", | ||
"password": "admin_password" | ||
} | ||
|
||
|
||
**Sample 200 Response Body:** | ||
:: | ||
{ | ||
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNTAyMzgzMDExfQ.3ZpcclxV6hN8ui2HUbwXLJsHl2lhesiCPeDVV2GIbJg" | ||
} | ||
|
||
Using a token | ||
^^^^^^^^^^^^^ | ||
|
||
For using JWT tokens you have to set ``Authorization`` header as follows: | ||
:: | ||
Authorization: JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNTAyMzgzMDExfQ.3ZpcclxV6hN8ui2HUbwXLJsHl2lhesiCPeDVV2GIbJg | ||
|
||
User secret | ||
^^^^^^^^^^^ | ||
|
||
To achieve ability to invalidate all user's tokens each user have their own secret key which is | ||
used to sign their tokens. The change of the secret will lead to invalidation of all user's | ||
tokens. The change is independent on password. | ||
|
||
You can reset user secret to random by setting ``reset_jwt_secret`` on user API endpoint to True. | ||
|
||
If you have enabled ``JWT_AUTH.JWT_ALLOW_SETTING_USER_SECRET`` you can set the user's secret | ||
via user API endpoint. | ||
|
||
The secret is stored in User model in field ``jwt_secret``. | ||
|
||
Offline token generation | ||
^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
If you have enabled ``JWT_AUTH.JWT_ALLOW_SETTING_USER_SECRET`` users can set their secrets and | ||
therefore are able to generate tokens offline. | ||
|
||
If you have pulpcore installed in your environment you can do the following: | ||
|
||
.. code-block:: python | ||
from datetime import timedelta | ||
from pulpcore.app.auth.jwt_utils import generate_token_offline | ||
username = "admin" | ||
jwt_secret = "admin_token_secret" | ||
exp_delta = timedelta(days=7) # This value is optional, default 14 days | ||
token = generate_token_offline(username, jwt_secret, exp_delta) | ||
If not you can implement the above function like this: | ||
|
||
.. code-block:: python | ||
import jwt # pip install pyjwt | ||
from datetime import datetime, timedelta | ||
def generate_token_offline(username, jwt_secret, exp_delta=timedelta(days=14)): | ||
""" | ||
Generate JWT token for pulp offline from username and secret. | ||
This function can be used for JWT token generation on client without | ||
the need of connection to pulp server. The only things you need to | ||
know are `username` and `jwt_secret`. | ||
Args: | ||
username (str): username | ||
jwt_secret (str): User's JWT token secret | ||
exp_delta (datetime.timedelta, optional): | ||
Token expiration time delta. This will be added to | ||
`datetime.utcnow()` to set the expiration time. | ||
If not set default 14 days is used. | ||
Returns: | ||
str: JWT token | ||
""" | ||
return jwt.encode( | ||
{ | ||
'username': username, | ||
'exp': datetime.utcnow() + exp_delta | ||
}, | ||
jwt_secret, | ||
'HS256', | ||
).decode("utf-8") | ||
.. warning:: | ||
When tokens are generated on client. The client can set **ANY** expiration time they want | ||
no matter what is set in ``JWT_EXPIRATION_DELTA``. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,7 @@ | ||
REST API Reference | ||
================== | ||
|
||
All REST API endpoints are protected with basic authentication. The password for the "admin" | ||
user can be set using two methods. | ||
.. toctree:: | ||
:maxdepth: 3 | ||
|
||
``pulp-manager reset-admin-password`` | ||
|
||
The above command prompts the user to enter a new password for "admin" user. | ||
|
||
``pulp-manager reset-admin-password --random`` | ||
|
||
The above command generates a random password for "admin" user and prints it to the screen. | ||
authentication |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import jwt | ||
from django.contrib.auth import get_user_model | ||
from django.utils.translation import ugettext as _ | ||
from rest_framework import exceptions | ||
from rest_framework_jwt.authentication import JSONWebTokenAuthentication | ||
from rest_framework_jwt.settings import api_settings | ||
|
||
|
||
class PulpJSONWebTokenAuthentication(JSONWebTokenAuthentication): | ||
""" | ||
Authenticate user by JWT token. | ||
""" | ||
|
||
def authenticate(self, request): | ||
""" | ||
Returns a two-tuple of `User` and token if a valid signature has been | ||
supplied using JWT-based authentication. Otherwise returns `None`. | ||
""" | ||
User = get_user_model() | ||
jwt_value = self.get_jwt_value(request) | ||
if jwt_value is None: | ||
return None | ||
|
||
try: | ||
payload = api_settings.JWT_DECODE_HANDLER(jwt_value) | ||
except User.DoesNotExist: | ||
msg = _('User not found.') | ||
raise exceptions.AuthenticationFailed(msg) | ||
except jwt.ExpiredSignature: | ||
msg = _('Token has expired.') | ||
raise exceptions.AuthenticationFailed(msg) | ||
except jwt.DecodeError: | ||
msg = _('Invalid token.') | ||
raise exceptions.AuthenticationFailed(msg) | ||
except jwt.InvalidTokenError: | ||
raise exceptions.AuthenticationFailed() | ||
|
||
user = self.authenticate_credentials(payload) | ||
|
||
return (user, jwt_value) | ||
|
||
def authenticate_credentials(self, payload): | ||
""" | ||
Returns an active user that matches the payload's user id and email. | ||
""" | ||
User = get_user_model() | ||
username = api_settings.JWT_PAYLOAD_GET_USERNAME_HANDLER(payload) | ||
|
||
if not username: | ||
msg = _('Invalid token.') | ||
raise exceptions.AuthenticationFailed(msg) | ||
|
||
try: | ||
user = User.objects.get_by_natural_key(username) | ||
except User.DoesNotExist: | ||
msg = _('Invalid token. User not found.') | ||
raise exceptions.AuthenticationFailed(msg) | ||
|
||
if not user.is_active: | ||
msg = _('Invalid token. User account is disabled.') | ||
raise exceptions.AuthenticationFailed(msg) | ||
|
||
return user |
Oops, something went wrong.