flow-models/python/points/authenticate.py
Jack Forgash 4df472bace
AN-5459/point transfers api integration (#378)
* point transfers api integration

* upd 2 silver models

* gha workflow with auth

* upd gha workflow

* add gha on push config for testing

* add print step

* chg echo

* upd auth.py

* rm run on commit from gha

* upd model tags

* merge 2 silver into 1, add yml, upd gha

* upd auth return vals

* add exit 1 on failure

* upd return on success True

* add gha on-run config for final test

* add backup default to env_var(JWT)

* add backup default to env_var(JWT) - 2

* rm run on commit from gha and upd sql limit for balance call

* add yml for evm address model

* add evm address threshold test

* upd gha workflow

* upd per CRs
2024-11-15 09:43:52 -07:00

137 lines
4.3 KiB
Python

import os
import sys
import requests
from eth_account import Account
from eth_account.messages import encode_defunct
from web3 import Web3
import json
from datetime import datetime
import logging
# Setup logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# Retrieve environment variables
FLOW_POINTS_URL = os.getenv('FLOW_POINTS_URL')
PRIVATE_KEY = os.getenv('PRIVATE_KEY')
PUBLIC_ADDRESS = os.getenv('PUBLIC_ADDRESS')
def verify_wallet_address(address):
"""
Verifies if the provided address is a valid Ethereum address.
Args:
address (str): The Ethereum address to verify.
Returns:
bool: Returns True if valid, False otherwise.
"""
if not Web3.is_address(address):
logger.error("Invalid Ethereum address format.")
return False
logger.info("The wallet address is valid and correctly formatted.")
return True
def authenticate_dapp():
"""
Authenticates the Dapp by generating a JWT.
Steps:
1. Create a Dapp Challenge.
2. Sign the challengeData using the private key.
3. Solve the Dapp Challenge to receive a JWT.
Returns:
str: The JWT token.
"""
if not PRIVATE_KEY or not PUBLIC_ADDRESS:
logger.error("Error: PRIVATE_KEY or PUBLIC_ADDRESS not set in environment.")
return False
# Verify the public address format
if not verify_wallet_address(PUBLIC_ADDRESS):
logger.error("Error: Invalid PUBLIC_ADDRESS format in environment.")
return False
try:
# Validate private key by attempting to create a wallet
_ = Account.from_key(PRIVATE_KEY)
logger.info("Wallet initialized successfully.")
# Step 1: Create Dapp Challenge
logger.info("Creating Dapp Challenge...")
challenge_endpoint = f"{FLOW_POINTS_URL}/points/dapp/challenge"
challenge_payload = {
"addressId": PUBLIC_ADDRESS.lower(),
}
headers = {
"Content-Type": "application/json"
}
challenge_response = requests.post(challenge_endpoint, headers=headers, json=challenge_payload)
if challenge_response.status_code != 200:
error_message = f"Failed to create Dapp challenge: {challenge_response.status_code} {challenge_response.reason}"
logger.error(error_message)
return False
challenge_data = challenge_response.json().get("challengeData")
logger.info("Dapp Challenge created successfully.")
# Step 2: Sign the challengeData
logger.info("Signing challengeData...")
message = encode_defunct(text=challenge_data)
signed_message = Account.sign_message(message, private_key=PRIVATE_KEY)
signature = f"0x{signed_message.signature.hex()}"
logger.info("challengeData signed successfully.")
# Step 3: Solve Dapp Challenge to get JWT
logger.info("Solving Dapp Challenge...")
solve_endpoint = f"{FLOW_POINTS_URL}/points/dapp/solve"
solve_payload = {
"challengeData": challenge_data,
"signature": signature,
}
solve_response = requests.post(solve_endpoint, headers=headers, json=solve_payload)
if solve_response.status_code != 200:
error_message = f"Failed to solve Dapp challenge: {solve_response.status_code} {solve_response.reason}"
logger.error(error_message)
return False
token = solve_response.json().get("token")
logger.info("JWT generated successfully.")
# Set the JWT as an environment variable
with open(os.environ['GITHUB_ENV'], 'a') as f:
f.write(f"JWT={token}\n")
return True
except requests.exceptions.RequestException as e:
error_message = f"HTTP Request failed: {e}"
logger.error(error_message)
return False
except Exception as e:
error_message = f"An unexpected error occurred: {e}"
logger.error(error_message)
return False
def main():
"""
Main function to execute the authentication process.
"""
if not authenticate_dapp():
logger.error("Authentication failed. Exiting with status code 1.")
sys.exit(1)
logger.info("Authentication succeeded.")
if __name__ == "__main__":
main()