identify-sdk 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- identify_sdk-0.1.0/PKG-INFO +53 -0
- identify_sdk-0.1.0/README.md +39 -0
- identify_sdk-0.1.0/identify_sdk/__init__.py +10 -0
- identify_sdk-0.1.0/identify_sdk/client.py +86 -0
- identify_sdk-0.1.0/identify_sdk/types.py +28 -0
- identify_sdk-0.1.0/identify_sdk.egg-info/PKG-INFO +53 -0
- identify_sdk-0.1.0/identify_sdk.egg-info/SOURCES.txt +10 -0
- identify_sdk-0.1.0/identify_sdk.egg-info/dependency_links.txt +1 -0
- identify_sdk-0.1.0/identify_sdk.egg-info/requires.txt +5 -0
- identify_sdk-0.1.0/identify_sdk.egg-info/top_level.txt +1 -0
- identify_sdk-0.1.0/pyproject.toml +22 -0
- identify_sdk-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: identify-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python client for the Identify auth service
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/1909-pramod/identify-sdk
|
|
7
|
+
Project-URL: Repository, https://github.com/1909-pramod/identify-sdk
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Requires-Dist: requests>=2.31
|
|
11
|
+
Provides-Extra: dev
|
|
12
|
+
Requires-Dist: mypy; extra == "dev"
|
|
13
|
+
Requires-Dist: types-requests; extra == "dev"
|
|
14
|
+
|
|
15
|
+
# identify-sdk (Python)
|
|
16
|
+
|
|
17
|
+
Python client for [identify](https://github.com/1909-pramod/identify-sdk) — a self-hosted modular authentication service.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install identify-sdk
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from identify_sdk import IdentifyClient, IdentifyError
|
|
29
|
+
|
|
30
|
+
client = IdentifyClient(base_url="http://localhost:8080")
|
|
31
|
+
|
|
32
|
+
# Exchange username + password for a JWT
|
|
33
|
+
resp = client.login_with_password("user@example.com", "secret")
|
|
34
|
+
token = resp.token
|
|
35
|
+
|
|
36
|
+
# Validate a JWT
|
|
37
|
+
result = client.validate_token(token)
|
|
38
|
+
print(result.valid, result.identity.primary_identifier)
|
|
39
|
+
|
|
40
|
+
# Get identity for an authenticated token
|
|
41
|
+
identity = client.get_me(token)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Error handling
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
try:
|
|
48
|
+
resp = client.login_with_password("user@example.com", "wrong")
|
|
49
|
+
except IdentifyError as e:
|
|
50
|
+
print(e.status_code, str(e)) # 401, "HTTP 401: ..."
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Full documentation: [github.com/1909-pramod/identify-sdk](https://github.com/1909-pramod/identify-sdk)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# identify-sdk (Python)
|
|
2
|
+
|
|
3
|
+
Python client for [identify](https://github.com/1909-pramod/identify-sdk) — a self-hosted modular authentication service.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install identify-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from identify_sdk import IdentifyClient, IdentifyError
|
|
15
|
+
|
|
16
|
+
client = IdentifyClient(base_url="http://localhost:8080")
|
|
17
|
+
|
|
18
|
+
# Exchange username + password for a JWT
|
|
19
|
+
resp = client.login_with_password("user@example.com", "secret")
|
|
20
|
+
token = resp.token
|
|
21
|
+
|
|
22
|
+
# Validate a JWT
|
|
23
|
+
result = client.validate_token(token)
|
|
24
|
+
print(result.valid, result.identity.primary_identifier)
|
|
25
|
+
|
|
26
|
+
# Get identity for an authenticated token
|
|
27
|
+
identity = client.get_me(token)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Error handling
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
try:
|
|
34
|
+
resp = client.login_with_password("user@example.com", "wrong")
|
|
35
|
+
except IdentifyError as e:
|
|
36
|
+
print(e.status_code, str(e)) # 401, "HTTP 401: ..."
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Full documentation: [github.com/1909-pramod/identify-sdk](https://github.com/1909-pramod/identify-sdk)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
import requests
|
|
5
|
+
|
|
6
|
+
from .types import Identity, TokenResponse, ValidateResponse
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class IdentifyError(Exception):
|
|
10
|
+
def __init__(self, status_code: int, message: str) -> None:
|
|
11
|
+
super().__init__(f"HTTP {status_code}: {message}")
|
|
12
|
+
self.status_code = status_code
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class IdentifyClient:
|
|
16
|
+
def __init__(self, base_url: str) -> None:
|
|
17
|
+
self._base_url = base_url.rstrip("/")
|
|
18
|
+
|
|
19
|
+
def _post(self, path: str, auth_header: str) -> dict[str, Any]:
|
|
20
|
+
resp = requests.post(
|
|
21
|
+
f"{self._base_url}{path}",
|
|
22
|
+
headers={"Authorization": auth_header},
|
|
23
|
+
)
|
|
24
|
+
body: dict[str, Any] = resp.json()
|
|
25
|
+
if not resp.ok:
|
|
26
|
+
raise IdentifyError(resp.status_code, body.get("error", "request failed"))
|
|
27
|
+
return body
|
|
28
|
+
|
|
29
|
+
def _get(self, path: str, token: str) -> dict[str, Any]:
|
|
30
|
+
resp = requests.get(
|
|
31
|
+
f"{self._base_url}{path}",
|
|
32
|
+
headers={"Authorization": f"Bearer {token}"},
|
|
33
|
+
)
|
|
34
|
+
body: dict[str, Any] = resp.json()
|
|
35
|
+
if not resp.ok:
|
|
36
|
+
raise IdentifyError(resp.status_code, body.get("error", "request failed"))
|
|
37
|
+
return body
|
|
38
|
+
|
|
39
|
+
@staticmethod
|
|
40
|
+
def _parse_identity(data: dict[str, Any]) -> Identity:
|
|
41
|
+
return Identity(
|
|
42
|
+
id=data["id"],
|
|
43
|
+
primary_identifier=data["primary_identifier"],
|
|
44
|
+
identifier_group_name=data.get("identifier_group_name"),
|
|
45
|
+
identifier_group_type=data.get("identifier_group_type"),
|
|
46
|
+
user_type=data.get("user_type"),
|
|
47
|
+
expiry_at=data.get("expiry_at"),
|
|
48
|
+
roles=data.get("roles"),
|
|
49
|
+
is_super_admin=data.get("is_super_admin", False),
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
@staticmethod
|
|
53
|
+
def _parse_token_response(data: dict[str, Any]) -> TokenResponse:
|
|
54
|
+
return TokenResponse(
|
|
55
|
+
token=data["token"],
|
|
56
|
+
token_type=data["token_type"],
|
|
57
|
+
expires_in=data["expires_in"],
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
def login_with_password(self, username: str, password: str) -> TokenResponse:
|
|
61
|
+
"""Exchange username/password for a JWT."""
|
|
62
|
+
encoded = base64.b64encode(f"{username}:{password}".encode()).decode()
|
|
63
|
+
return self._parse_token_response(self._post("/auth", f"Basic {encoded}"))
|
|
64
|
+
|
|
65
|
+
def login_with_google(self, google_id_token: str) -> TokenResponse:
|
|
66
|
+
"""Exchange a Google ID token for an internal JWT."""
|
|
67
|
+
return self._parse_token_response(
|
|
68
|
+
self._post("/auth", f"Bearer {google_id_token}")
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
def refresh_token(self, token: str) -> TokenResponse:
|
|
72
|
+
"""Exchange an existing internal JWT for a fresh one."""
|
|
73
|
+
return self._parse_token_response(self._post("/auth", f"Bearer {token}"))
|
|
74
|
+
|
|
75
|
+
def validate_token(self, token: str) -> ValidateResponse:
|
|
76
|
+
"""Validate a JWT and return the resolved identity."""
|
|
77
|
+
data = self._post("/token", f"Bearer {token}")
|
|
78
|
+
return ValidateResponse(
|
|
79
|
+
valid=data["valid"],
|
|
80
|
+
identity=self._parse_identity(data["identity"]),
|
|
81
|
+
expires_at=data.get("expires_at"),
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
def get_me(self, token: str) -> Identity:
|
|
85
|
+
"""Return the identity for the authenticated token."""
|
|
86
|
+
return self._parse_identity(self._get("/me", token))
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@dataclass
|
|
6
|
+
class Identity:
|
|
7
|
+
id: int
|
|
8
|
+
primary_identifier: str
|
|
9
|
+
identifier_group_name: Optional[str] = None
|
|
10
|
+
identifier_group_type: Optional[str] = None
|
|
11
|
+
user_type: Optional[str] = None
|
|
12
|
+
expiry_at: Optional[str] = None
|
|
13
|
+
roles: Optional[list[str]] = None
|
|
14
|
+
is_super_admin: bool = False
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class TokenResponse:
|
|
19
|
+
token: str
|
|
20
|
+
token_type: str
|
|
21
|
+
expires_in: int
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass
|
|
25
|
+
class ValidateResponse:
|
|
26
|
+
valid: bool
|
|
27
|
+
identity: Identity
|
|
28
|
+
expires_at: Optional[str] = None
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: identify-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python client for the Identify auth service
|
|
5
|
+
License: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/1909-pramod/identify-sdk
|
|
7
|
+
Project-URL: Repository, https://github.com/1909-pramod/identify-sdk
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Requires-Dist: requests>=2.31
|
|
11
|
+
Provides-Extra: dev
|
|
12
|
+
Requires-Dist: mypy; extra == "dev"
|
|
13
|
+
Requires-Dist: types-requests; extra == "dev"
|
|
14
|
+
|
|
15
|
+
# identify-sdk (Python)
|
|
16
|
+
|
|
17
|
+
Python client for [identify](https://github.com/1909-pramod/identify-sdk) — a self-hosted modular authentication service.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install identify-sdk
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from identify_sdk import IdentifyClient, IdentifyError
|
|
29
|
+
|
|
30
|
+
client = IdentifyClient(base_url="http://localhost:8080")
|
|
31
|
+
|
|
32
|
+
# Exchange username + password for a JWT
|
|
33
|
+
resp = client.login_with_password("user@example.com", "secret")
|
|
34
|
+
token = resp.token
|
|
35
|
+
|
|
36
|
+
# Validate a JWT
|
|
37
|
+
result = client.validate_token(token)
|
|
38
|
+
print(result.valid, result.identity.primary_identifier)
|
|
39
|
+
|
|
40
|
+
# Get identity for an authenticated token
|
|
41
|
+
identity = client.get_me(token)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Error handling
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
try:
|
|
48
|
+
resp = client.login_with_password("user@example.com", "wrong")
|
|
49
|
+
except IdentifyError as e:
|
|
50
|
+
print(e.status_code, str(e)) # 401, "HTTP 401: ..."
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Full documentation: [github.com/1909-pramod/identify-sdk](https://github.com/1909-pramod/identify-sdk)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
identify_sdk/__init__.py
|
|
4
|
+
identify_sdk/client.py
|
|
5
|
+
identify_sdk/types.py
|
|
6
|
+
identify_sdk.egg-info/PKG-INFO
|
|
7
|
+
identify_sdk.egg-info/SOURCES.txt
|
|
8
|
+
identify_sdk.egg-info/dependency_links.txt
|
|
9
|
+
identify_sdk.egg-info/requires.txt
|
|
10
|
+
identify_sdk.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
identify_sdk
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "identify-sdk"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Python client for the Identify auth service"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
dependencies = ["requests>=2.31"]
|
|
13
|
+
|
|
14
|
+
[project.urls]
|
|
15
|
+
Homepage = "https://github.com/1909-pramod/identify-sdk"
|
|
16
|
+
Repository = "https://github.com/1909-pramod/identify-sdk"
|
|
17
|
+
|
|
18
|
+
[project.optional-dependencies]
|
|
19
|
+
dev = ["mypy", "types-requests"]
|
|
20
|
+
|
|
21
|
+
[tool.mypy]
|
|
22
|
+
strict = true
|