Source code for wp_api.auth

"""
Authentication methods for the WordPress REST API
"""

import base64
import requests
from typing import Dict, Optional
import urllib.parse
import hmac
import hashlib
import time
import random
import string
import uuid


[docs] class BasicAuth: """ Basic Authentication for WordPress REST API Note: This method is not recommended for production use unless over HTTPS """
[docs] def __init__(self, username: str, password: str): """ Initialize Basic Authentication Args: username (str): WordPress username password (str): WordPress password """ self.username = username self.password = password
[docs] def authenticate(self, session: requests.Session) -> None: """ Add authentication to session Args: session (requests.Session): The session to authenticate """ auth_string = f"{self.username}:{self.password}" encoded_auth = base64.b64encode(auth_string.encode()).decode() session.headers.update({"Authorization": f"Basic {encoded_auth}"})
[docs] class ApplicationPasswordAuth: """ Application Password Authentication for WordPress REST API This is the recommended authentication method for WordPress 5.6+ """
[docs] def __init__(self, username: str, app_password: str): """ Initialize Application Password Authentication Args: username (str): WordPress username app_password (str): Application password generated in WordPress admin """ self.username = username self.app_password = app_password
[docs] def authenticate(self, session: requests.Session) -> None: """ Add authentication to session Args: session (requests.Session): The session to authenticate """ auth_string = f"{self.username}:{self.app_password}" encoded_auth = base64.b64encode(auth_string.encode()).decode() session.headers.update({"Authorization": f"Basic {encoded_auth}"})
[docs] class OAuth1: """ OAuth1 Authentication for WordPress REST API """
[docs] def __init__( self, consumer_key: str, consumer_secret: str, token: Optional[str] = None, token_secret: Optional[str] = None ): """ Initialize OAuth1 Authentication Args: consumer_key (str): OAuth consumer key consumer_secret (str): OAuth consumer secret token (str, optional): OAuth token token_secret (str, optional): OAuth token secret """ self.consumer_key = consumer_key self.consumer_secret = consumer_secret self.token = token self.token_secret = token_secret
[docs] def authenticate(self, session: requests.Session) -> None: """ Add authentication to session Args: session (requests.Session): The session to authenticate """ # Patch session to use OAuth1 original_request = session.request def oauth_request(method, url, **kwargs): # Add OAuth1 headers oauth_params = self._get_oauth_params(method, url, kwargs.get('params', {})) headers = kwargs.get('headers', {}) headers['Authorization'] = self._build_auth_header(oauth_params) kwargs['headers'] = headers return original_request(method, url, **kwargs) session.request = oauth_request
def _get_oauth_params(self, method: str, url: str, params: Dict) -> Dict: """Generate OAuth parameters""" oauth_params = { 'oauth_consumer_key': self.consumer_key, 'oauth_nonce': uuid.uuid4().hex, 'oauth_signature_method': 'HMAC-SHA1', 'oauth_timestamp': str(int(time.time())), 'oauth_version': '1.0', } if self.token: oauth_params['oauth_token'] = self.token # Generate signature base_string = self._get_base_string(method, url, {**params, **oauth_params}) signing_key = self._get_signing_key() signature = self._get_signature(base_string, signing_key) oauth_params['oauth_signature'] = signature return oauth_params def _get_base_string(self, method: str, url: str, params: Dict) -> str: """Generate OAuth base string""" # Sort parameters by key sorted_params = sorted(params.items()) # Encode parameters encoded_params = urllib.parse.urlencode(sorted_params) # Create base string base_parts = [ method.upper(), urllib.parse.quote(url, safe=''), urllib.parse.quote(encoded_params, safe='') ] return '&'.join(base_parts) def _get_signing_key(self) -> str: """Generate OAuth signing key""" consumer_secret = urllib.parse.quote(self.consumer_secret, safe='') if self.token_secret: token_secret = urllib.parse.quote(self.token_secret, safe='') return f"{consumer_secret}&{token_secret}" return f"{consumer_secret}&" def _get_signature(self, base_string: str, signing_key: str) -> str: """Generate OAuth signature""" signature = hmac.new( signing_key.encode(), base_string.encode(), hashlib.sha1 ) return base64.b64encode(signature.digest()).decode() def _build_auth_header(self, oauth_params: Dict) -> str: """Build OAuth Authorization header""" auth_header_parts = [] for key, value in sorted(oauth_params.items()): auth_header_parts.append(f'{urllib.parse.quote(key, safe="")}="{urllib.parse.quote(value, safe="")}"') return f"OAuth {', '.join(auth_header_parts)}"