Metadata-Version: 2.4
Name: flashauth
Version: 0.2.0
Summary: Secure, minimal authentication for FastAPI and Python 3.13+
Project-URL: Homepage, https://github.com/yourusername/flashauth
Project-URL: Documentation, https://github.com/yourusername/flashauth#readme
Project-URL: Repository, https://github.com/yourusername/flashauth
Project-URL: Changelog, https://github.com/yourusername/flashauth/blob/main/CHANGELOG.md
Author-email: Aviral <your-email@example.com>
License-Expression: MIT
License-File: LICENSE
Keywords: argon2,authentication,fastapi,jwt,password-hashing,python313
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: pwdlib[argon2]<1.0.0,>=0.2.0
Requires-Dist: python-jose[cryptography]<4.0.0,>=3.3.0
Provides-Extra: dev
Requires-Dist: mypy>=1.0.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
Requires-Dist: pytest>=7.0.0; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Description-Content-Type: text/markdown

# ⚡ FlashAuth

Secure, minimal authentication for FastAPI and Python 3.13+.

No 72-byte password limits. No deprecated dependencies. Just works.

## Why FlashAuth?

| Problem | FlashAuth Solution |
|---------|-------------------|
| bcrypt truncates passwords at 72 bytes | Argon2id with no limits |
| passlib breaks on Python 3.13 | No crypt module dependency |
| 80+ lines of auth boilerplate | One import, done |
| Can't distinguish expired vs invalid tokens | Separate exceptions |
| No refresh token support | Built-in token pairs |
| Password verify blocks async | `hash_async()` / `verify_async()` |

## Installation
```bash
pip install flashauth
```

## Quick Start
```python
from flashauth import FlashAuth

# Initialize (store secret_key securely in production)
auth = FlashAuth(secret_key=FlashAuth.generate_secret_key())

# Hash passwords (no length limit)
hashed = auth.hash("my-very-long-secure-password-🚀")

# Verify with automatic rehash detection
result = auth.verify("my-very-long-secure-password-🚀", hashed)
if result.valid:
    if result.needs_rehash:
        # Save result.new_hash to upgrade security params
        pass

# Create JWT
token = auth.create_token({"user_id": 123})

# Decode with proper error handling
from flashauth import TokenExpiredError, TokenInvalidError

try:
    payload = auth.decode_token(token)
except TokenExpiredError:
    # Handle expired token (e.g., prompt re-login)
    pass
except TokenInvalidError:
    # Handle invalid token (e.g., log suspicious activity)
    pass
```

## FastAPI Integration
```python
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from flashauth import FlashAuth, TokenExpiredError, TokenInvalidError

auth = FlashAuth(
    secret_key="your-secret-key-min-32-bytes-long!",
    issuer="myapp",
)
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")


async def get_current_user(token: str = Depends(oauth2_scheme)):
    try:
        payload = auth.decode_token(token)
    except TokenExpiredError:
        raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Token expired")
    except TokenInvalidError:
        raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Invalid token")
    
    return await get_user(payload["user_id"])


@app.post("/login")
async def login(username: str, password: str):
    user = await get_user_by_username(username)
    result = await auth.verify_async(password, user.password_hash)
    
    if not result.valid:
        raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Invalid credentials")
    
    tokens = auth.create_token_pair({"user_id": user.id})
    return {"access_token": tokens.access_token, "refresh_token": tokens.refresh_token}
```

## Features

- **Argon2id hashing** - No 72-byte limit, memory-hard
- **Python 3.13 ready** - No deprecated crypt module
- **Async support** - `hash_async()`, `verify_async()`
- **Refresh tokens** - `create_token_pair()`, `refresh_tokens()`
- **Key rotation** - `old_secret_keys` parameter
- **Token revocation** - `jti` claim + `get_token_id()`
- **Auto-rehashing** - `VerifyResult.needs_rehash`

## License

MIT