Authentication
The YouVersion Bible Client uses OAuth2 authentication to securely access the YouVersion API.
How Authentication Works
OAuth2 Token Request: The client sends credentials to YouVersion’s OAuth2 endpoint
Token Response: YouVersion returns an access token (JWT)
Token Decoding: The client decodes the JWT to extract user information
Authenticated Requests: All subsequent requests include the Bearer token
Authentication Flow
from youversion.clients import AsyncClient
async with AsyncClient() as client:
# Authentication happens automatically on first API call
# The client:
# 1. Gets OAuth2 token
# 2. Decodes JWT to extract user_id
# 3. Stores token for subsequent requests
votd = await client.verse_of_the_day()
# Token is automatically included in request headers
Token Management
The client automatically manages authentication tokens:
Automatic Authentication: Tokens are obtained on first API call
Token Caching: Tokens are cached for the client instance lifetime
Automatic Refresh: Tokens are refreshed as needed
Cleanup: Tokens are cleared when client is closed
Accessing User Information
After authentication, you can access user information:
from youversion.clients import SyncClient
with SyncClient() as client:
# Get username
username = client.username
print(f"Authenticated as: {username}")
# Get user ID (available after first API call)
# Make any API call first
client.verse_of_the_day()
user_id = client.user_id
print(f"User ID: {user_id}")
Authentication Errors
Common authentication errors and solutions:
ValueError: Missing Credentials
Error: .. code-block:: text
ValueError: Username and password must be provided either as arguments or as YOUVERSION_USERNAME and YOUVERSION_PASSWORD environment variables
Solution: Provide credentials via environment variables, .env file, or constructor arguments.
HTTP 403: Forbidden
Error: .. code-block:: text
httpx.HTTPStatusError: 403 Forbidden
Solution: Your account may not have access to the requested resource. Check your account permissions.
Token Expiration
Access tokens may expire. The client handles this automatically:
from youversion.clients import AsyncClient
import asyncio
async def long_running_task():
async with AsyncClient() as client:
# Token obtained here
votd1 = await client.verse_of_the_day()
# Wait a long time...
await asyncio.sleep(3600) # 1 hour
# If token expired, client will re-authenticate automatically
votd2 = await client.verse_of_the_day()
asyncio.run(long_running_task())
Best Practices
Reuse Client Instances: Create one client and reuse it for multiple requests
Use Context Managers: Always use
async withorwithfor automatic cleanupHandle Errors Gracefully: Catch and handle authentication errors appropriately
Don’t Share Tokens: Each client instance manages its own tokens
Secure Credentials: Never log or expose credentials in error messages
Example: Secure Authentication
import os
from youversion.clients import AsyncClient
import httpx
async def secure_authenticate():
# Get credentials from secure source
username = os.getenv("YOUVERSION_USERNAME")
password = os.getenv("YOUVERSION_PASSWORD")
if not username or not password:
raise ValueError("Credentials not found in environment")
try:
async with AsyncClient(username=username, password=password) as client:
# Verify authentication works
votd = await client.verse_of_the_day()
print(f"Authenticated successfully as: {client.username}")
return client
except httpx.HTTPStatusError as e:
if e.response.status_code == 401:
raise ValueError("Invalid credentials")
raise
# Usage
import asyncio
client = asyncio.run(secure_authenticate())