105 lines
3.2 KiB
Python
105 lines
3.2 KiB
Python
"""
|
|
One-time Adobe Sign OAuth setup.
|
|
|
|
Run this script once to authorize the app and save tokens to .env:
|
|
python src/auth_adobe.py
|
|
|
|
Prerequisites:
|
|
- Set ADOBE_CLIENT_ID and ADOBE_CLIENT_SECRET in .env (or export them)
|
|
- Redirect URI in your Adobe Sign app must be set to: https://localhost
|
|
|
|
After authorizing in the browser, the page will fail to load (that's expected).
|
|
Copy the full URL from the address bar and paste it when prompted.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import webbrowser
|
|
from urllib.parse import urlencode, urlparse, parse_qs
|
|
|
|
from dotenv import load_dotenv, set_key
|
|
import requests
|
|
|
|
load_dotenv()
|
|
|
|
SHARD = "eu2"
|
|
AUTH_URL = f"https://secure.{SHARD}.adobesign.com/public/oauth/v2"
|
|
TOKEN_URL = f"https://api.{SHARD}.adobesign.com/oauth/v2/token"
|
|
REDIRECT_URI = "https://localhost:8080/callback"
|
|
SCOPES = "library_read:self library_write:self user_read:self"
|
|
ENV_FILE = os.path.join(os.path.dirname(__file__), "..", ".env")
|
|
|
|
|
|
def get_auth_url(client_id):
|
|
params = {
|
|
"redirect_uri": REDIRECT_URI,
|
|
"response_type": "code",
|
|
"client_id": client_id,
|
|
"scope": SCOPES,
|
|
}
|
|
return f"{AUTH_URL}?{urlencode(params)}"
|
|
|
|
|
|
def extract_code(redirected_url):
|
|
parsed = urlparse(redirected_url)
|
|
params = parse_qs(parsed.query)
|
|
if "code" not in params:
|
|
error = params.get("error_description", params.get("error", ["unknown"]))[0]
|
|
raise ValueError(f"No code in URL. Error: {error}")
|
|
return params["code"][0]
|
|
|
|
|
|
def exchange_code_for_tokens(code, client_id, client_secret):
|
|
data = {
|
|
"grant_type": "authorization_code",
|
|
"code": code,
|
|
"redirect_uri": REDIRECT_URI,
|
|
"client_id": client_id,
|
|
"client_secret": client_secret,
|
|
}
|
|
resp = requests.post(TOKEN_URL, data=data)
|
|
resp.raise_for_status()
|
|
return resp.json()
|
|
|
|
|
|
def save_tokens(tokens):
|
|
abs_env = os.path.abspath(ENV_FILE)
|
|
set_key(abs_env, "ADOBE_ACCESS_TOKEN", tokens["access_token"])
|
|
if "refresh_token" in tokens:
|
|
set_key(abs_env, "ADOBE_REFRESH_TOKEN", tokens["refresh_token"])
|
|
set_key(abs_env, "ADOBE_SIGN_BASE_URL", f"https://api.{SHARD}.adobesign.com/api/rest/v6")
|
|
print(f"Tokens saved to {abs_env}")
|
|
|
|
|
|
def main():
|
|
client_id = os.getenv("ADOBE_CLIENT_ID")
|
|
client_secret = os.getenv("ADOBE_CLIENT_SECRET")
|
|
|
|
if not client_id or not client_secret:
|
|
print("ERROR: ADOBE_CLIENT_ID and ADOBE_CLIENT_SECRET must be set in .env")
|
|
sys.exit(1)
|
|
|
|
url = get_auth_url(client_id)
|
|
print(f"\nOpening browser for authorization...")
|
|
print(f"\nIf the browser doesn't open, go to:\n{url}\n")
|
|
webbrowser.open(url)
|
|
|
|
print("After authorizing, the browser will land on a page that fails to load.")
|
|
print("That's expected — just copy the full URL from the address bar and paste it here.\n")
|
|
redirected_url = input("Paste the redirect URL: ").strip()
|
|
|
|
try:
|
|
code = extract_code(redirected_url)
|
|
except ValueError as e:
|
|
print(f"ERROR: {e}")
|
|
sys.exit(1)
|
|
|
|
print("Exchanging code for tokens...")
|
|
tokens = exchange_code_for_tokens(code, client_id, client_secret)
|
|
save_tokens(tokens)
|
|
print("Done. You can now run the migrator.")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|