DCI authentication module used by dci-control-server and python-dciclient
Project description
# python-dciauth
DCI authentication module used by dci-control-server and python-dciclient
## Summary of signing steps
To create a signed request, complete the following:
* Task 1: Hash payload you want to send
* Task 2: Create a string to sign
Create a string to sign with the request and extra information such as the request date, and the payload (hash) of the request.
* Task 3: Calculate the signature for DCI
Derive a signing key by performing a succession of keyed hash operations (HMAC operations) on the string to sign, with your API secret.
* Task 4: Add the Signing Information to the Request
After you calculate the signature, add it to an HTTP header or to the query string of the request.
## Summary of the validation steps
* Task 1: Hash payload you received
* Task 2: Create a string to sign
Create a string to sign with the request and extra information such as the request date **header**, and the payload (hash) of the request.
* Task 3: Calculate the signature for DCI
Derive a signing key by performing a succession of keyed hash operations (HMAC operations) on the string to sign, with user's API secret.
* Task 4: Compare signature calculated with signature send
After you calculate the signature, compare it to an HTTP header.
* Task 5: Reject any request older than 5 minutes
## Signing example:
```python
from dciauth import signature
secret = "Y4efRHLzw2bC2deAZNZvxeeVvI46Cx8XaLYm47Dc019S6bHKejSBVJiGAfHbZLIN"
method = "GET"
content_type = 'application/json'
url = "/api/v1/jobs"
query_string = "limit=100&offset=1"
payload = {}
headers = signature.generate_headers_with_secret(
secret,
method,
content_type,
url,
query_string,
payload)
# headers == {
# 'Authorization': 'DCI-HMAC-SHA256 811f7ceb089872cd264fc5859cffcd6ddfbe8ce851f0743199ad4c96470c6b6b',
# 'Content-Type: 'application/json',
# 'DCI-Datetime': '20171103T162727Z'
# }
```
## Validation example
```python
from dciauth import signature
secret = "Y4efRHLzw2bC2deAZNZvxeeVvI46Cx8XaLYm47Dc019S6bHKejSBVJiGAfHbZLIN"
method = "GET"
headers = {
'Authorization': 'DCI-HMAC-SHA256 811f7ceb089872cd264fc5859cffcd6ddfbe8ce851f0743199ad4c96470c6b6b',
'DCI-Datetime': '20171103T162727Z',
'Content-type': 'application/json'
}
url = "/api/v1/jobs"
query_string = "limit=100&offset=1"
payload = {}
expected_signature = signature.calculate_signature(
secret,
method,
headers,
url,
query_string,
payload)
dci_signature = signature.get_signature_from_headers(headers)
if signature.equals(expected_signature, dci_signature):
raise Exception("Authentication failed: signature invalid")
if signature.is_expired(headers):
raise Exception("Authentication failed: signature expired")
```
## Validation example with flask request
```python
from dciauth import signature
from flask import request
secret = "Y4efRHLzw2bC2deAZNZvxeeVvI46Cx8XaLYm47Dc019S6bHKejSBVJiGAfHbZLIN"
headers = request.headers
expected_signature = signature.calculate_signature(
secret,
method = request.method,
headers = headers,
url = request.path,
query_string = request.query_string.decode('utf-8'),
payload = request.get_json(silent=True)
)
dci_signature = signature.get_signature_from_headers(headers)
if signature.equals(expected_signature, dci_signature):
raise Exception("Authentication failed: signature invalid")
if signature.is_expired(headers):
raise Exception("Authentication failed: signature expired")
```
## Implementation details
Along each request, the client must add the three following HTTP headers:
* `Authorization`
* `Content-Type`
* `DCI-Datetime`
They are build as following
### Content-Type
`Content-Type` (e.g.: `application/json`) of the request
### DCI-Datetime
`DCI-Datetime` is the current client timestamp in UTC timezone with the following format: `%Y%m%dT%H%M%SZ` (e.g.: `20170612T142917Z`)
### Authorization
The signature header `Authorization:<algorithm> <signature>` is obtained with:
* `<algorithm>`: only `DCI-HMAC-SHA256`
* `<signature>`: `hexdigest( HMAC-SHA256( <api secret>, <string_to_sign>.encode('utf-8') ) )`
* `<string_to_sign>`:
<HTTP Verb> + "\n"
<Content-Type> + "\n"
<timestamp> + "\n"
<url> + "\n"
<query_string> + "\n"
<payload hash>
* `<HTTP Verb>`: the HTTP method used in uppercase
* `<Content-Type>`: Usually `application/json` for API calls
* `<timestamp>`: as previously, the client timestamp in UTC timezone with the following format: `%Y%m%dT%H%M%SZ`
* `<url>`: the resource path, without query string
* `<query_string>`: the parameter passed when querying (the part after the `?` in the full URL)
* `<payload hash>`: `hexdigest( SHA256( payload ) )`
See `tests/test_signature.py` for some detailed examples
## License
Apache 2.0
## Author Information
Distributed-CI Team <distributed-ci@redhat.com>
DCI authentication module used by dci-control-server and python-dciclient
## Summary of signing steps
To create a signed request, complete the following:
* Task 1: Hash payload you want to send
* Task 2: Create a string to sign
Create a string to sign with the request and extra information such as the request date, and the payload (hash) of the request.
* Task 3: Calculate the signature for DCI
Derive a signing key by performing a succession of keyed hash operations (HMAC operations) on the string to sign, with your API secret.
* Task 4: Add the Signing Information to the Request
After you calculate the signature, add it to an HTTP header or to the query string of the request.
## Summary of the validation steps
* Task 1: Hash payload you received
* Task 2: Create a string to sign
Create a string to sign with the request and extra information such as the request date **header**, and the payload (hash) of the request.
* Task 3: Calculate the signature for DCI
Derive a signing key by performing a succession of keyed hash operations (HMAC operations) on the string to sign, with user's API secret.
* Task 4: Compare signature calculated with signature send
After you calculate the signature, compare it to an HTTP header.
* Task 5: Reject any request older than 5 minutes
## Signing example:
```python
from dciauth import signature
secret = "Y4efRHLzw2bC2deAZNZvxeeVvI46Cx8XaLYm47Dc019S6bHKejSBVJiGAfHbZLIN"
method = "GET"
content_type = 'application/json'
url = "/api/v1/jobs"
query_string = "limit=100&offset=1"
payload = {}
headers = signature.generate_headers_with_secret(
secret,
method,
content_type,
url,
query_string,
payload)
# headers == {
# 'Authorization': 'DCI-HMAC-SHA256 811f7ceb089872cd264fc5859cffcd6ddfbe8ce851f0743199ad4c96470c6b6b',
# 'Content-Type: 'application/json',
# 'DCI-Datetime': '20171103T162727Z'
# }
```
## Validation example
```python
from dciauth import signature
secret = "Y4efRHLzw2bC2deAZNZvxeeVvI46Cx8XaLYm47Dc019S6bHKejSBVJiGAfHbZLIN"
method = "GET"
headers = {
'Authorization': 'DCI-HMAC-SHA256 811f7ceb089872cd264fc5859cffcd6ddfbe8ce851f0743199ad4c96470c6b6b',
'DCI-Datetime': '20171103T162727Z',
'Content-type': 'application/json'
}
url = "/api/v1/jobs"
query_string = "limit=100&offset=1"
payload = {}
expected_signature = signature.calculate_signature(
secret,
method,
headers,
url,
query_string,
payload)
dci_signature = signature.get_signature_from_headers(headers)
if signature.equals(expected_signature, dci_signature):
raise Exception("Authentication failed: signature invalid")
if signature.is_expired(headers):
raise Exception("Authentication failed: signature expired")
```
## Validation example with flask request
```python
from dciauth import signature
from flask import request
secret = "Y4efRHLzw2bC2deAZNZvxeeVvI46Cx8XaLYm47Dc019S6bHKejSBVJiGAfHbZLIN"
headers = request.headers
expected_signature = signature.calculate_signature(
secret,
method = request.method,
headers = headers,
url = request.path,
query_string = request.query_string.decode('utf-8'),
payload = request.get_json(silent=True)
)
dci_signature = signature.get_signature_from_headers(headers)
if signature.equals(expected_signature, dci_signature):
raise Exception("Authentication failed: signature invalid")
if signature.is_expired(headers):
raise Exception("Authentication failed: signature expired")
```
## Implementation details
Along each request, the client must add the three following HTTP headers:
* `Authorization`
* `Content-Type`
* `DCI-Datetime`
They are build as following
### Content-Type
`Content-Type` (e.g.: `application/json`) of the request
### DCI-Datetime
`DCI-Datetime` is the current client timestamp in UTC timezone with the following format: `%Y%m%dT%H%M%SZ` (e.g.: `20170612T142917Z`)
### Authorization
The signature header `Authorization:<algorithm> <signature>` is obtained with:
* `<algorithm>`: only `DCI-HMAC-SHA256`
* `<signature>`: `hexdigest( HMAC-SHA256( <api secret>, <string_to_sign>.encode('utf-8') ) )`
* `<string_to_sign>`:
<HTTP Verb> + "\n"
<Content-Type> + "\n"
<timestamp> + "\n"
<url> + "\n"
<query_string> + "\n"
<payload hash>
* `<HTTP Verb>`: the HTTP method used in uppercase
* `<Content-Type>`: Usually `application/json` for API calls
* `<timestamp>`: as previously, the client timestamp in UTC timezone with the following format: `%Y%m%dT%H%M%SZ`
* `<url>`: the resource path, without query string
* `<query_string>`: the parameter passed when querying (the part after the `?` in the full URL)
* `<payload hash>`: `hexdigest( SHA256( payload ) )`
See `tests/test_signature.py` for some detailed examples
## License
Apache 2.0
## Author Information
Distributed-CI Team <distributed-ci@redhat.com>
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
dciauth-1.0.0.tar.gz
(7.8 kB
view details)
Built Distribution
File details
Details for the file dciauth-1.0.0.tar.gz
.
File metadata
- Download URL: dciauth-1.0.0.tar.gz
- Upload date:
- Size: 7.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | ce9213705baee99075369b8528b7e5972b5a8792d4a901624c4a3de7ce25e944 |
|
MD5 | 157a520434087b94401a29e356922292 |
|
BLAKE2b-256 | b7d59a19198112295c7471db3e26edf5e3879b06a2212fb409d8ba6f3ac9736d |
File details
Details for the file dciauth-1.0.0-py2-none-any.whl
.
File metadata
- Download URL: dciauth-1.0.0-py2-none-any.whl
- Upload date:
- Size: 7.4 kB
- Tags: Python 2
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | b7891b0610e6b538bb8870aa89afa511274c89a278721072c621b8f533dbf1e2 |
|
MD5 | 93b591b756f747334eab809fdef27287 |
|
BLAKE2b-256 | fba2dd1dd70047e07ecc503d417ff37dc12eb868c5fea7f9c5fe0e157736031d |