Metadata-Version: 2.4
Name: anzar
Version: 0.5.3
Summary: Anzar is a lightweight authentication and authorization framework that runs as a separate microservice
Keywords: Software Development,Authentication,Authorization,MicroService
Author: Hakou Guelfen
Author-email: Hakou Guelfen <hakoudev@gmail.com>
License-Expression: GPL-3.0
Classifier: Programming Language :: Python :: 3
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Topic :: Software Development
Requires-Dist: httpx>=0.28.1
Requires-Dist: pydantic>=2.12.5
Requires-Dist: flask>=3.1.3 ; extra == 'flask'
Requires-Dist: pyjwt>=2.12.1 ; extra == 'flask'
Requires-Dist: redis>=7.3.0 ; extra == 'redis'
Requires-Python: >=3.11
Project-URL: Bug, https://gitlab.com/anzar_software/python-sdk/-/work_items
Project-URL: Documentation, https://anzar_software.gitlab.io/docs
Project-URL: Homepage, https://gitlab.com/anzar_software/python-sdk
Provides-Extra: flask
Provides-Extra: redis
Description-Content-Type: text/markdown

# Anzar SDK Documentation

## Server Middleware
The server SDK provides two middleware functions for protecting your routes using JWT tokens issued by your Anzar Auth container.

📝 **Note:**
    **JWT** vs. **Session**

    Depending on what Authentication strategy you choose, use these middleware functions accordingly

---

### Jwt
**`require_auth`**

Verifies the JWT token and attaches the authenticated user's ID to the request object. Use this to protect any route that requires a logged-in user.

```python
import os

from flask import g
from flask import Flask, jsonify
from anzar.server.flask import require_auth, JwtAuth

app = Flask(__name__)

jwt_auth = JwtAuth(
    secret = os.getenv("SECRET"),
    audience = os.getenv("AUDIENCE"),
    issuerBaseURL = os.getenv("ISSUER"),
)

@app.route("/protected")
@require_jwt(jwt_auth)
def me():
    return jsonify(g.user_id)
```

---

**`require_role`**

Verifies the JWT token **and** checks that the token includes a specific role. Use this to restrict routes to users with a particular permission level.
```python
import os

from flask import g
from flask import Flask, jsonify
from anzar.server.flask import require_role, JwtAuth

app = Flask(__name__)

jwt_auth = JwtAuth(
    secret = os.getenv("SECRET"),
    audience = os.getenv("AUDIENCE"),
    issuerBaseURL = os.getenv("ISSUER"),
)

@app.route("/admin")
@require_role(jwt_auth, roles="admin", permissions=["users:delete"])
def admin():
    return jsonify(f"admin panel, {g.user_id}")
```

---

### Session
**`require_auth`**

Verifies the session and attaches the authenticated user's ID to the request object. Use this to protect routes when using session-based authentication instead of JWT tokens.

```python
import os

from flask import g
from flask import Flask, jsonify
from anzar.server.flask import require_auth, SessionAuth

app = Flask(__name__)

session_auth = SessionAuth()

@app.route("/protected")
@require_session(session_auth)
def me():
    return jsonify(g.user_id)
```

---

**`require_role`**

Verifies the session and checks that the session includes a specific role. Use this to restrict routes to users with a particular permission level when using session-based authentication instead of JWT tokens.

```python
import os

from flask import g
from flask import Flask, jsonify
from anzar.server import require_role, SessionAuth

app = Flask(__name__)

session_auth = SessionAuth()

@app.route("/admin")
@require_session_role(session_auth, roles="admin", permissions=["users:delete"])
def admin():
    return jsonify(f"admin panel, {g.user_id}")
```


---


## Client

## Install The Python SDK
In a python project run the following command to install the anzar package.

**uv**
```bash
$ uv add anzar
```

**pip**
```bash
# in a virtual env run
$ pip install anzar
```

## Create Anzar Auth Instance
in your main entry file (`main.py` for example),
import `anzar.yml` and parse it as a YAML file
```python
def load_config(path: str) -> AnzarConfig:
    import yaml

    try:
        with open(path, "r") as f:
            data = yaml.safe_load(f)
        return AnzarConfig(**data)
    except Exception as e:
        import sys

        sys.exit("check your configuration file: anzar.yml")
```

import Anzar Auth and create your auth instance
```python 
# Initialize once at application startup
# The SDK will communicate with your Anzar container at the configured api_url
from anzar import Anzar

config = load_config("anzar.yml")
anzar = Anzar(config, options=None)
```


**Note** "Configuring Token Persistence"
    To keep users logged in across restarts, choose a token storage adapter.

    ```python
    from anzar.adapters import RedisStorage
    from anzar.types import SdkOptions 

    anzar = Anzar(config, SdkOptions(storage=RedisStorage()))
    ```

---

## Basic Usage
Anzar provides authentication support for email and password.

📝 **Note:** Other methods of authentication will be implemented later

### Sign Up
To sign up a user you need to call the method register with the user's information.
```python
from anzar.types import AuthResponse, ErrorCode

(data, error) = await anzar.Auth.register({
  "username": "username",
  "email": "user@example.com",
  "password": "password"
})

if data:
    print(data)

if error:
    if error.code == ErrorCode.InvalidCredentials:
        show_error("Invalid email or password.")
    elif error.code == ErrorCode.AccountNotVerified:
        show_error("Please verify your email before logging in.")
```

📝 **Note:** By default, the users are automatically signed in after they successfully sign up.
             Disabling this behavior will be implemented later

### Sign In
To sign in a user you need to call the method login.
```python
from anzar.types import ApiException, AuthResponse, ErrorCode

(response, error) = await anzar.Auth.login(
    LoginRequest(email="user@example.com", password="password")
)
if error:
    print("code:", error.code)
    print("message:", error.message)
print(response)
