Metadata-Version: 2.1
Name: cheq-rti-wsgi-middleware
Version: 0.0.3
Summary: cheq middlewares for wsgi application
Home-page: https://github.com/cheq-ai/Cheq-Python-Middlewares
Author: CHEQ.AI
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE

# cheq-rti-wsgi-middleware
CHEQ Real Time Interception middleware for Python 3 wsgi application



## Features

* [Installation](#installation)
* [Real time interception](#real-time-interception)
    * [Required configuration](#required-configuration)
        * [API key](#api-key)
        * [Tag hash](#tag-hash)
        * [API endpoint](#api-endpoint)
    * [Optional configuration](#optional-configuration)
        * [Mode](#mode)
        * [Event Type](#event-type)
        * [Threat type codes](#threat-type-codes)
        * [Redirect URL](#redirect-url)
        * [Callback function](#callback-function)
        * [Ja3](#ja3)
        * [Resource type](#resource-type)
        * [IP header](#ip-header)
        * [URI Exclusion](#uri-exclusion)
        * [Timeout](#timeout)
        * [Custom event name](#custom-event-name)
    * [Usage example](#usage-example)
        * [Flask](#flask)
        * [Django](#django)
   


## Installation
````bash
$ pip install cheq-rti-wsgi-middleware
````

## Real time interception

Real-Time Interception (RTI) supports API calls to provide detection of invalid traffic (IVT) to your site, in absolute real-time.  RTI will intercept IVT to prevent invalid visitors from harming your conversion efforts.

### Configuration

#### Required configuration

##### API key

Available on the Paradome platform under “Management -> RTI”

```` python
options = {
    ...
    'api_key': '11abc111-aa11-11aa-1111-11a11a11111'
    ...
}
````

##### Tag hash

Appears in your CHEQ tag. 

```` python
options = {
    ...
    'tag_hash': 'c99651e7936e27743ce51c728492aac9'
    ...
}
````

##### API endpoint
The nearest API endpoint to your server. Must be the same region as your tag domain.<br>Select the appropriate endpoint:
- US: https://rti-us-east-1.cheqzone.com
- EU: https://rti-eu-west-1.cheqzone.com

```` python
options = {
    ...
    'api_endpoint': 'https://rti-eu-west1.cheqzone.com'
    ...
}
````

#### Optional configuration

##### Mode

- `monitoring` - Will not perform any action

- `blocking` - Will block Invalid traffic or redirect them to a different url (defind in [Redirect URL](#redirect-url)).

The default value will be `monitoring`.

```` python
options = {
    ...
    'mode': 'blocking'
    ...
}
````

##### Event type

- `route_to_event_type` - A dictionary of routes as keys and cheq event type as value.<br> Default `page_load` will be used as event type   

```` python
options = {
    ...
    'route_to_event_type': {
        '/': 'page_load',
        '/subscribe': 'subscribe',
        .....
        .....
    }
    ...
}
````

##### Threat type codes

Threat types are devided to two groups:

1. Block/Redirect - traffic detected as threat types in this group would be blocked or redirected to a different page (defind in [Redirect URL](#redirect-url).<br>
        Default threat type codes for this group:  2,3,6,7,10,11,16,18.
        
2. Captcha - threat type codes in this group would be reffered to [Callback function](#callback-function). <br>
        Default threat type codes for this group:  4,5,13,14,15,17.
Threat type must be unique for each list. 

```` python
options = {
    ...
    'invalid_block_redirect_codes': [2, 3, 6, 7, 10, 11, 16, 18],
    'invalid_captcha_codes': [4, 5, 13, 14, 15, 17]
    ...
};
````
##### Redirect URL

A URL you would like to redirect invalid users to. 

If it is empty the response will be status code 403 and the user will be blocked.

```` python
options = {
    ...
     'redirect_url': 'https://invalid-user.com'
    ...
}
````

##### Callback function

A custom callback option, for instance to redirect to captcha page.
If it is empty, will use start_response to route.

```` python
def callback(app, environ, start_response):
     #do somthing or call app(environ, start_response)
     
options = {
    ...
     'callback': callback 
    ...
}
````
##### Ja3

Recommended - A function that extracts ja3 fingerprint from the request.<br>
SSL/TLS client fingerprints

```` python
from urllib.parse import urlparse
from urllib.parse import parse_qs

def get_ja3(request):
        parsed_url = urlparse(reuest.url)
        captured_value = parse_qs(parsed_url.query)['ja3'][0] 
options = {
    ... 
    'get_ja3': get_ja3
    ...
}
````
##### Resource type

A function to get the response content-type header. 

This is recommended to improve detection.

```` python
def get_resource_type(request):
    if request.headers.environ['REQUEST_METHOD'] == 'POST'):
        return 'application/json'
    elif request.pth == '/':
        return 'text/html'

options = {
  ...
  'get_resource_type': get_resource_type
  ...
}
````

##### IP header

Specify a trusted IP header to be used as client IP
```` python
options = {
  ...
  'trusted_ip_header': 'client-ip'
  ...
};
````

##### URI Exclusion

An array of regular expressions or path that will be excluded

```` python
options = {
  ...
  'uri_exclusion': ['/about', '/careers']
  ...
};
````


##### Timeout

Optional timeout in milliseconds, if absent value will be set to 100 milliseconds.

```` python
options = {
    ...
     'timeout': 1000 // one second
    ...
}
````

##### Custom event name

In case a custom event name is used, this function extracts the name of the custom event.<br> 

```` python
from urllib.parse import urlparse
from urllib.parse import parse_qs

def get_channel(request):
        parsed_url = urlparse(reuest.url)
        captured_value = parse_qs(parsed_url.query)['channel'][0] 
options = {
    ...
     'get_channel': get_channel
    ...
}
````



### Usage example

##### Flask
```` python
from flask import Flask
from cheq_wsgi_middlewares.RtiWsgiMiddleware import RtiMiddleware

api_key = "62fdc812-be58-492f-9417-66a1f22b4da1"
tag_hash = "5f863bea211c957865e067b148f2471b"
app = Flask(__name__)


options = {
    'app': app.wsgi_app,
    'api_key': "62fdc812-be58-492f-9417-66a1f22b4da1",
    'tag_hash': "5f863bea211c957865e067b148f2471b",
    'api_endpoint': 'https://rti-us-east-1.cheqzone.com',
    'route_to_event_type': dict(),
    'mode': 'blocking',
    'uri_exclusion': [],
    'invalid_block_redirect_codes': [],
    'invalid_captcha_codes': [],
    'trusted_ip_header': 'Client-Ip'

}


app.wsgi_app = RtiMiddleware(options)


@app.route("/")
def index():
    return "Hello World"


if __name__ == '__main__':
    app.run('0.0.0.0', 8080)
````
##### Django
```` python
from django.core.wsgi import get_wsgi_application
from cheq_wsgi_middlewares.RtiWsgiMiddleware import RtiMiddleware
import os

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hellodjango.settings")
application = get_wsgi_application()

options = {
    'app': application,
    'api_key': "62fdc812-be58-492f-9417-66a1f22b4da1",
    'tag_hash': "5f863bea211c957865e067b148f2471b",
    'api_endpoint': 'https://rti-us-east-1.cheqzone.com',
    'route_to_event_type': dict(),
    'mode': 'blocking',
    'uri_exclusion': [],
    'invalid_block_redirect_codes': [],
    'invalid_captcha_codes': [],
    'trusted_ip_header': 'Client-Ip'

}


application = RtiMiddleware(options)

````

