Created
July 25, 2024 16:48
-
-
Save ivorpad/d0e427438a6d94dd9593dc24d1053f5f to your computer and use it in GitHub Desktop.
This script is a Bash utility for managing OAuth 2.0 authentication with the Xero API.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
source ./send_email.sh | |
# OAuth 2.0 configuration | |
CLIENT_ID="" | |
CLIENT_SECRET="" | |
REDIRECT_URI="http://localhost:3000/api/xoauth/callback" | |
AUTH_URL="https://login.xero.com/identity/connect/authorize" | |
TOKEN_URL="https://identity.xero.com/connect/token" | |
SCOPES="openid profile email accounting.attachments.read accounting.budgets.read accounting.contacts.read accounting.journals.read accounting.reports.read accounting.reports.tenninetynine.read accounting.settings.read accounting.transactions.read assets.read offline_access" | |
REDIS_URL="" | |
save_tokens_to_redis() { | |
local tokens="$1" | |
/usr/local/bin/redis-cli -u "$REDIS_URL" SET xero_tokens "$tokens" | |
} | |
save_state_to_redis() { | |
local state="$1" | |
/usr/local/bin/redis-cli -u "$REDIS_URL" SET xero_state:$state "$state" | |
} | |
get_tokens_from_redis() { | |
/usr/local/bin/redis-cli -u "$REDIS_URL" GET xero_tokens | |
} | |
get_state_from_redis() { | |
local state="$1" | |
/usr/local/bin/redis-cli -u "$REDIS_URL" GET xero_state:$state | |
} | |
generate_auth_url() { | |
STATE=$(openssl rand -hex 16) | |
AUTH_REQUEST_URL="${AUTH_URL}?response_type=code&client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI}&scope=${SCOPES}&state=${STATE}" | |
save_state_to_redis "$STATE" | |
echo "$AUTH_REQUEST_URL" | |
} | |
refresh_token() { | |
local refresh_token="$1" | |
TOKEN_RESPONSE=$(curl -s -X POST ${TOKEN_URL} \ | |
-H "Content-Type: application/x-www-form-urlencoded" \ | |
-d "grant_type=refresh_token" \ | |
-d "refresh_token=${refresh_token}" \ | |
-d "client_id=${CLIENT_ID}" \ | |
-d "client_secret=${CLIENT_SECRET}") | |
if echo "$TOKEN_RESPONSE" | jq -e '.access_token' > /dev/null; then | |
echo "Token refreshed successfully." | |
save_tokens_to_redis "$TOKEN_RESPONSE" | |
echo "New tokens saved to Redis." | |
else | |
echo "Error refreshing token. Response:" | |
echo "$TOKEN_RESPONSE" | |
AUTH_URL=$(generate_auth_url) | |
AUTH_URL=$(echo "$AUTH_URL" | sed 's/^OK[[:space:]]*//' | tr -d '\n') | |
TEXT_MESSAGE="Token refresh failed. Please re-authorize: $AUTH_URL" | |
HTML_MESSAGE="Token refresh failed. Please <a href=\"$AUTH_URL\">re-authorize</a>" | |
send_email "$TEXT_MESSAGE" "$HTML_MESSAGE" | |
exit 1 | |
fi | |
} | |
exchange_code_for_tokens() { | |
local auth_code="$1" | |
TOKEN_RESPONSE=$(curl -s -X POST ${TOKEN_URL} \ | |
-H "Content-Type: application/x-www-form-urlencoded" \ | |
-d "grant_type=authorization_code" \ | |
-d "code=${auth_code}" \ | |
-d "redirect_uri=${REDIRECT_URI}" \ | |
-d "client_id=${CLIENT_ID}" \ | |
-d "client_secret=${CLIENT_SECRET}") | |
if echo "$TOKEN_RESPONSE" | jq -e '.access_token' > /dev/null; then | |
echo "Authorization code exchanged successfully." | |
save_tokens_to_redis "$TOKEN_RESPONSE" | |
echo "Tokens saved to Redis." | |
else | |
echo "Error exchanging authorization code. Response:" | |
echo "$TOKEN_RESPONSE" | |
exit 1 | |
fi | |
} | |
case "$1" in | |
--refresh) | |
echo "Refreshing token..." | |
STORED_TOKENS=$(get_tokens_from_redis) | |
REFRESH_TOKEN=$(echo $STORED_TOKENS | jq -r '.refresh_token') | |
if [ -z "$REFRESH_TOKEN" ]; then | |
echo "Error: Refresh token not found in Redis" | |
AUTH_URL=$(generate_auth_url) | |
AUTH_URL=$(echo "$AUTH_URL" | sed 's/^OK[[:space:]]*//' | tr -d '\n') | |
TEXT_MESSAGE="Refresh token not found in Redis: $REDIS_URL. Please re-authorize: $AUTH_URL" | |
HTML_MESSAGE="Refresh token not found in Redis: $REDIS_URL. Please <a href=\"$AUTH_URL\">re-authorize</a>" | |
send_email "$TEXT_MESSAGE" "$HTML_MESSAGE" | |
exit 1 | |
fi | |
refresh_token "$REFRESH_TOKEN" | |
;; | |
--code) | |
if [ -z "$2" ]; then | |
echo "Error: Authorization code not provided" | |
exit 1 | |
fi | |
echo "Exchanging authorization code for tokens..." | |
exchange_code_for_tokens "$2" | |
;; | |
"") | |
# Generate a random state value | |
STATE=$(openssl rand -hex 16) | |
# Construct the authorization URL | |
AUTH_REQUEST_URL=$(generate_auth_url) | |
echo "Please visit this URL in a browser on your local machine to authorize the application:" | |
echo $AUTH_REQUEST_URL | |
echo | |
echo "After authorization, you will be redirected to a URL starting with $REDIRECT_URI" | |
echo "Look for the 'code' parameter in this URL." | |
echo | |
# Wait for the authorization code | |
read -p "Enter the authorization code from the redirect URL: " AUTH_CODE | |
exchange_code_for_tokens "$AUTH_CODE" | |
;; | |
*) | |
echo "Usage: $0 [--refresh | --code <authorization_code>]" | |
exit 1 | |
;; | |
esac | |
# Use the new access token to update configuration | |
STORED_TOKENS=$(get_tokens_from_redis) | |
NEW_ACCESS_TOKEN=$(echo $STORED_TOKENS | jq -r '.access_token') | |
CURL_RESPONSE=$(curl --request PATCH \ | |
--url 'http://localhost:8000/api/public/v1/sources/<source_id>' \ | |
--header 'accept: application/json' \ | |
--header 'authorization: Basic base64(username:password)' \ | |
--header 'Content-Type: application/json' \ | |
--data "{ | |
\"configuration\": { | |
\"credentials\": { | |
\"access_token\": \"$NEW_ACCESS_TOKEN\" | |
} | |
} | |
}") | |
echo "CURL Response:" | |
echo "$CURL_RESPONSE" | |
if echo "$CURL_RESPONSE" | jq -e '.sourceId' > /dev/null; then | |
echo "Configuration updated successfully." | |
echo "Updated source details:" | |
echo "$CURL_RESPONSE" | jq '.' | |
else | |
echo "Error updating configuration. Response:" | |
echo "$CURL_RESPONSE" | |
send_email "Error updating configuration: $CURL_RESPONSE" "Error updating configuration: $CURL_RESPONSE" | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment