Skip to content

Commit 7bbbd2c

Browse files
author
Inbal Tako
committed
Update readme
1 parent bbd4dfd commit 7bbbd2c

6 files changed

Lines changed: 110 additions & 213 deletions

File tree

README.md

Lines changed: 102 additions & 209 deletions
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,3 @@
1-
# Python SDK for Secure Native
2-
3-
## How to get it?
4-
the python SDK is published to PyPi so you can just use `pip` to install it:
5-
```bash
6-
pip install securenative
7-
```
8-
9-
## Initialize the SDK
10-
Go to the settings page of your SecureNative account and find your API key, afterwards add this line on your application main module.
11-
```python
12-
import securenative
13-
14-
# Many lines of code ...
15-
16-
if __name__=='__main__':
17-
# Your bootstrap code
18-
securenative.init('API_KEY') # Should be called before any other call to secure native
19-
```
20-
21-
## Tracking Events (async)
22-
Once the SDK has been initialized, you can start sending new events with the `track` function:
23-
```python
24-
import securenative
25-
from securenative.event_options import Event, User
26-
27-
def my_login_function():
28-
# Many lines of code ...
29-
30-
event = Event( # Build the event from the request's context
31-
event_type=securenative.event_types.login,
32-
ip='35.199.23.1',
33-
remote_ip='35.199.23.2',
34-
user_agent='Mozilla/5.0 (Linux; U; Android 4.4.2; zh-cn; GT-I9500 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 MQQBrowser/5.0 QQ-URL-Manager Mobile Safari/537.36',
35-
sn_cookie_value='eyJjaWQiOiJkYzgyYjdhZS00ODFkLTQyODItYTMyZC0xZTU1Njk2ZjNmZTQiLCJmcCI6Ijk5NGYzZjVjZTRiYWUwODQzMTRhOTFkNzgyN2I1MWYuMjQ3MDBmOWYxOTg2ODAwYWI0ZmNjODgwNTMwZGQwZWQifQ',
36-
user=User(
37-
user_id='1',
38-
user_email='1@example.com',
39-
user_name='example example'
40-
)
41-
)
42-
43-
# Track it:
44-
securenative.track(event)
45-
46-
# Many lines of code ...
47-
48-
```
49-
50-
## Verification Events (sync)
51-
Once the SDK has been initialized, you can protect sensitive operation by calling the `verify` function, this function will return the risk analysis of the current user.
52-
53-
```python
54-
import securenative
55-
from securenative.event_options import Event, User
56-
57-
def my_change_password_function():
58-
# Many lines of code...
59-
60-
event = Event( # Build the event from the request's context
61-
event_type=securenative.event_types.verify,
62-
ip='35.199.23.1',
63-
remote_ip='35.199.23.2',
64-
user_agent='Mozilla/5.0 (Linux; U; Android 4.4.2; zh-cn; GT-I9500 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 MQQBrowser/5.0 QQ-URL-Manager Mobile Safari/537.36',
65-
sn_cookie_value='eyJjaWQiOiJkYzgyYjdhZS00ODFkLTQyODItYTMyZC0xZTU1Njk2ZjNmZTQiLCJmcCI6Ijk5NGYzZjVjZTRiYWUwODQzMTRhOTFkNzgyN2I1MWYuMjQ3MDBmOWYxOTg2ODAwYWI0ZmNjODgwNTMwZGQwZWQifQ',
66-
user=User(
67-
user_id='1',
68-
user_email='1@example.com',
69-
user_name='example example'
70-
)
71-
)
72-
73-
result = securenative.verify(event)
74-
if result['riskLevel'] == 'high':
75-
return 'Cannot change password'
76-
elif result['riskLevel'] == 'medium':
77-
return 'MFA'
78-
79-
# Many lines of code...
80-
```
81-
82-
## Verifying Incoming Webhooks
83-
You can use the SDK to verify incoming webhooks from Secure Native, just call the `veriy_webhook` function which return a boolean which indicates if the webhook came from Secure Native servers.
84-
```python
85-
import securenative
86-
87-
@post('/sn/webhook')
88-
def sn_webhook_handler(headers, body):
89-
sig_header = headers["X-SecureNative"]
90-
if securenative.verify_webhook(sig_header, body):
91-
# Handle the webhook
92-
level = body['riskLevel']
93-
pass
94-
else:
95-
# This reqeust wasn't sent from Secure Native servers, you can dismiss/investigate it
96-
pass
97-
98-
```
99-
1001
<p align="center">
1012
<a href="https://www.securenative.com"><img src="https://user-images.githubusercontent.com/45174009/77826512-f023ed80-7120-11ea-80e0-58aacde0a84e.png" alt="SecureNative Logo"/></a>
1023
</p>
@@ -108,9 +9,6 @@ def sn_webhook_handler(headers, body):
1089
<a href="https://github.com/securenative/securenative-python">
10910
<img alt="Github Actions" src="https://github.com/securenative/securenative-java/workflows/CI/badge.svg">
11011
</a>
111-
<a href="https://codecov.io/gh/securenative/securenative-python">
112-
<img src="https://codecov.io/gh/securenative/securenative-java/branch/master/graph/badge.svg" />
113-
</a>
11412
</p>
11513
<p align="center">
11614
<a href="https://docs.securenative.com">Documentation</a> |
@@ -123,154 +21,149 @@ def sn_webhook_handler(headers, body):
12321

12422
[SecureNative](https://www.securenative.com/) performs user monitoring by analyzing user interactions with your application and various factors such as network, devices, locations and access patterns to stop and prevent account takeover attacks.
12523

126-
## Install the SDK
127-
128-
When using Maven, add the following dependency to your `pom.xml` file:
129-
```xml
130-
<dependency>
131-
<groupId>com.securenative.java</groupId>
132-
<artifactId>sdk-base</artifactId>
133-
<version>LATEST</version>
134-
</dependency>
135-
```
13624

137-
When using Gradle, add the following dependency to your `build.gradle` file:
138-
```gradle
139-
compile group: 'com.securenative.java', name: 'sdk-parent', version: '0.3.1', ext: 'pom'
140-
```
25+
## Install the SDK
14126

142-
When using SBT, add the following dependency to your `build.sbt` file:
143-
```sbt
144-
libraryDependencies += "com.securenative.java" % "sdk-parent" % "0.3.1" pomOnly()
27+
When using PyPi, run the following:
28+
```bash
29+
pip install securenative
14530
```
14631

14732
## Initialize the SDK
14833

14934
To get your *API KEY*, login to your SecureNative account and go to project settings page:
15035

15136
### Option 1: Initialize via Config file
152-
SecureNative can automatically load your config from *securenative.properties* file or from the file that is specified in your *SECURENATIVE_CONFIG_FILE* env variable:
37+
SecureNative can automatically load your config from *securenative.ini* file or from the file that is specified in your *SECURENATIVE_CONFIG_FILE* env variable:
15338

154-
```java
155-
SecureNative secureNative = SecureNative.init();
39+
```python
40+
from securenative.securenative import SecureNative
41+
42+
43+
secureative = SecureNative.init()
15644
```
15745
### Option 2: Initialize via API Key
15846

159-
```java
160-
SecureNative secureNative = SecureNative.init("YOUR_API_KEY");
47+
```python
48+
from securenative.securenative import SecureNative
49+
50+
51+
securenative = SecureNative.init_with_api_key("YOUR_API_KEY")
16152
```
16253

16354
### Option 3: Initialize via ConfigurationBuilder
164-
```java
165-
SecureNative secureNative = SecureNative.init(SecureNative.configBuilder()
166-
.withApiKey("API_KEY")
167-
.withMaxEvents(10)
168-
.withLogLevel("error")
169-
.build());
55+
```python
56+
from securenative.securenative import SecureNative
57+
58+
59+
securenative = SecureNative.init_with_options(SecureNative.config_builder()
60+
.with_api_key("API_KEY")
61+
.with_max_events(10)
62+
.with_log_level("ERROR")
63+
.build())
17064
```
17165

17266
## Getting SecureNative instance
17367
Once initialized, sdk will create a singleton instance which you can get:
174-
```java
175-
SecureNative secureNative = SecureNative.getInstance();
68+
```python
69+
from securenative.securenative import SecureNative
70+
71+
72+
secureNative = SecureNative.get_instance()
17673
```
17774

17875
## Tracking events
17976

18077
Once the SDK has been initialized, tracking requests sent through the SDK
18178
instance. Make sure you build event with the EventBuilder:
18279

183-
```java
184-
SecureNative secureNative = SecureNative.getInstance();
185-
186-
SecureNativeContext context = SecureNative.contextBuilder()
187-
.withIp("127.0.0.1")
188-
.withClientToken("SECURED_CLIENT_TOKEN")
189-
.withHeaders(Maps.defaultBuilder()
190-
.put("user-agent", "Mozilla/5.0 (iPad; U; CPU OS 3_2_1 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Mobile/7B405")
191-
.build())
192-
.build();
193-
194-
EventOptions eventOptions = EventOptionsBuilder.builder(EventTypes.LOG_IN)
195-
.userId("USER_ID")
196-
.userTraits("USER_NAME", "USER_EMAIL")
197-
.context(context)
198-
.properties(Maps.builder()
199-
.put("prop1", "CUSTOM_PARAM_VALUE")
200-
.put("prop2", true)
201-
.put("prop3", 3)
202-
.build())
203-
.timestamp(new Date())
204-
.build();
205-
206-
secureNative.track(eventOptions);
80+
```python
81+
from securenative.securenative import SecureNative
82+
from securenative.event_options_builder import EventOptionsBuilder
83+
from securenative.enums.event_types import EventTypes
84+
from securenative.models.user_traits import UserTraits
85+
86+
87+
securenative = SecureNative.get_instance()
88+
89+
context = SecureNative.context_builder().\
90+
with_ip("127.0.0.1").\
91+
with_client_token("SECURED_CLIENT_TOKEN").\
92+
with_headers({"user-agent", "Mozilla/5.0 (iPad; U; CPU OS 3_2_1 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Mobile/7B405"}).\
93+
build()
94+
95+
event_options = EventOptionsBuilder(EventTypes.LOG_IN).\
96+
with_user_id("USER_ID").\
97+
with_user_traits(UserTraits("USER_NAME", "USER_EMAIL")).\
98+
with_context(context).\
99+
with_properties({"prop1": "CUSTOM_PARAM_VALUE", "prop2": True, "prop3": 3}).\
100+
build()
101+
102+
securenative.track(event_options)
207103
```
208104

209-
You can also create request context from HttpServletRequest:
210-
211-
```java
212-
@RequestMapping("/track")
213-
public void track(HttpServletRequest request, HttpServletResponse response) {
214-
SecureNativeContext context = SecureNative.contextBuilder()
215-
.fromHttpServletRequest(request)
216-
.build();
217-
218-
EventOptions eventOptions = EventOptionsBuilder.builder(EventTypes.LOG_IN)
219-
.userId("USER_ID")
220-
.userTraits("USER_NAME", "USER_EMAIL")
221-
.context(context)
222-
.properties(Maps.builder()
223-
.put("prop1", "CUSTOM_PARAM_VALUE")
224-
.put("prop2", true)
225-
.put("prop3", 3)
226-
.build())
227-
.timestamp(new Date())
228-
.build();
105+
You can also create request context from requests:
106+
107+
```python
108+
from securenative.securenative import SecureNative
109+
from securenative.event_options_builder import EventOptionsBuilder
110+
from securenative.enums.event_types import EventTypes
111+
from securenative.models.user_traits import UserTraits
112+
113+
114+
def track(request):
115+
securenative = SecureNative.get_instance()
116+
context = SecureNative.context_builder().from_http_request(request).build()
117+
118+
event_options = EventOptionsBuilder(EventTypes.LOG_IN).\
119+
with_user_id("USER_ID").\
120+
with_user_traits(UserTraits("USER_NAME", "USER_EMAIL")).\
121+
with_context(context).\
122+
with_properties({"prop1": "CUSTOM_PARAM_VALUE", "prop2": True, "prop3": 3}).\
123+
build()
229124

230-
secureNative.track(eventOptions);
231-
}
125+
securenative.track(event_options)
232126
```
233127

234128
## Verify events
235129

236130
**Example**
237131

238-
```java
239-
@RequestMapping("/track")
240-
public void track(HttpServletRequest request, HttpServletResponse response) {
241-
SecureNativeContext context = SecureNative.contextBuilder()
242-
.fromHttpServletRequest(request)
243-
.build();
244-
245-
EventOptions eventOptions = EventOptionsBuilder.builder(EventTypes.LOG_IN)
246-
.userId("USER_ID")
247-
.userTraits("USER_NAME", "USER_EMAIL")
248-
.context(context)
249-
.properties(Maps.builder()
250-
.put("prop1", "CUSTOM_PARAM_VALUE")
251-
.put("prop2", true)
252-
.put("prop3", 3)
253-
.build())
254-
.timestamp(new Date())
255-
.build();
132+
```python
133+
from securenative.securenative import SecureNative
134+
from securenative.event_options_builder import EventOptionsBuilder
135+
from securenative.enums.event_types import EventTypes
136+
from securenative.models.user_traits import UserTraits
137+
138+
139+
def track(request):
140+
securenative = SecureNative.get_instance()
141+
context = SecureNative.context_builder().from_http_request(request).build()
142+
143+
event_options = EventOptionsBuilder(EventTypes.LOG_IN).\
144+
with_user_id("USER_ID").\
145+
with_user_traits(UserTraits("USER_NAME", "USER_EMAIL")).\
146+
with_context(context).\
147+
with_properties({"prop1": "CUSTOM_PARAM_VALUE", "prop2": True, "prop3": 3}).\
148+
build()
256149

257-
VerifyResult verifyResult = secureNative.verify(eventOptions);
258-
verifyResult.getRiskLevel() // Low, Medium, High
259-
verifyResult.score() // Risk score: 0 -1 (0 - Very Low, 1 - Very High)
260-
verifyResult.getTriggers() // ["TOR", "New IP", "New City"]
261-
}
150+
verify_result = securenative.verify(event_options)
151+
verify_result.risk_level # Low, Medium, High
152+
verify_result.score # Risk score: 0 -1 (0 - Very Low, 1 - Very High)
153+
verify_result.triggers # ["TOR", "New IP", "New City"]
262154
```
263155

264156
## Webhook signature verification
265157

266-
Apply our filter to verify the request is from us, example in spring:
158+
Apply our filter to verify the request is from us, for example:
159+
160+
```python
161+
from securenative.securenative import SecureNative
162+
267163

268-
```java
269-
@RequestMapping("/webhook")
270-
public void webhookEndpoint(HttpServletRequest request, HttpServletResponse response) {
271-
SecureNative secureNative = SecureNative.getInstance();
164+
def webhook_endpoint(request):
165+
securenative = SecureNative.get_instance()
272166

273-
// Checks if request is verified
274-
Boolean isVerified = secureNative.verifyRequestPayload(request);
275-
}
167+
# Checks if request is verified
168+
is_verified = securenative.verify_request_payload(request)
276169
```

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
requests~=2.23.0
22
pycrypto~=2.6.1
3-
crypto==1.4.1
3+
crypto==1.4.1

securenative/securenative.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,7 @@ def verify(self, event_options):
8383
@classmethod
8484
def _flush(cls):
8585
cls._securenative = None
86+
87+
# TODO!
88+
def verify_request_payload(self, request):
89+
pass

securenative/utils/encryption_utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ def encrypt(cls, text, cipher_key):
1616
key = cipher_key[:cls.KEY_SIZE]
1717
iv = Random.new().read(AES.block_size)
1818
cipher = AES.new(key, AES.MODE_CBC, iv)
19-
raw = cls._pad(text)
20-
return hexlify(iv + cipher.encrypt(raw)).decode('utf-8')
19+
raw = str(cls._pad(text))
20+
return hexlify(iv + cipher.encrypt(raw))
2121

2222
@classmethod
2323
def decrypt(cls, encrypted, cipher_key):

0 commit comments

Comments
 (0)