get-token.sh 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #!/usr/bin/env bash
  2. set -euo pipefail
  3. # Get an OAuth 2.1 access token through the full flow:
  4. # 1. Register a client (if needed)
  5. # 2. Login as admin
  6. # 3. Generate PKCE
  7. # 4. Authorize with consent
  8. # 5. Exchange code for token
  9. # 6. Print the access token
  10. BASE_URL="${BASE_URL:-http://localhost:3000}"
  11. REDIRECT_URI="${REDIRECT_URI:-http://localhost/callback}"
  12. ADMIN_EMAIL="${ADMIN_EMAIL:-admin@delete.me}"
  13. ADMIN_PASSWORD="${ADMIN_PASSWORD:-deleteme}"
  14. SCOPE="${SCOPE:-llm}"
  15. COOKIE_FILE="${COOKIE_FILE:-cookies.txt}"
  16. # Colors for output
  17. GREEN='\033[0;32m'
  18. BLUE='\033[0;34m'
  19. YELLOW='\033[1;33m'
  20. RED='\033[0;31m'
  21. NC='\033[0m' # No Color
  22. # ---------------------------------------------------------------------------
  23. # Step 1: Register a Client
  24. # ---------------------------------------------------------------------------
  25. echo -e "${BLUE}=== Step 1: Register OAuth Client ===${NC}"
  26. REGISTER_RESPONSE=$(curl -s -X POST "${BASE_URL}/oauth/register" \
  27. -H "Content-Type: application/json" \
  28. -d "{
  29. \"client_name\": \"get-token-script\",
  30. \"redirect_uris\": [\"${REDIRECT_URI}\"],
  31. \"grant_types\": [\"authorization_code\"],
  32. \"response_types\": [\"code\"],
  33. \"scope\": \"${SCOPE}\",
  34. \"token_endpoint_auth_method\": \"client_secret_basic\"
  35. }")
  36. # Extract client credentials
  37. CLIENT_ID=$(echo "$REGISTER_RESPONSE" | grep -o '"client_id":"[^"]*"' | cut -d'"' -f4 || true)
  38. CLIENT_SECRET=$(echo "$REGISTER_RESPONSE" | grep -o '"client_secret":"[^"]*"' | cut -d'"' -f4 || true)
  39. if [ -z "$CLIENT_ID" ] || [ -z "$CLIENT_SECRET" ]; then
  40. echo -e "${RED}Failed to register client. Response:${NC}"
  41. echo "$REGISTER_RESPONSE"
  42. exit 1
  43. fi
  44. echo -e "${GREEN}Client ID:${NC} $CLIENT_ID"
  45. echo -e "${GREEN}Client Secret:${NC} $CLIENT_SECRET"
  46. # ---------------------------------------------------------------------------
  47. # Step 2: Login (Get Session Cookie)
  48. # ---------------------------------------------------------------------------
  49. echo -e "${BLUE}=== Step 2: Login ===${NC}"
  50. # Remove old cookie file if it exists
  51. rm -f "$COOKIE_FILE"
  52. LOGIN_RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "${BASE_URL}/oauth/login" \
  53. -H "Content-Type: application/x-www-form-urlencoded" \
  54. -d "email=${ADMIN_EMAIL}" \
  55. -d "password=${ADMIN_PASSWORD}" \
  56. -c "$COOKIE_FILE" \
  57. -o /dev/null)
  58. HTTP_CODE=$(echo "$LOGIN_RESPONSE" | tail -n1)
  59. if [ "$HTTP_CODE" != "302" ] && [ "$HTTP_CODE" != "200" ]; then
  60. echo -e "${RED}Login failed (HTTP $HTTP_CODE). Check credentials.${NC}"
  61. exit 1
  62. fi
  63. # Verify cookie was set
  64. if ! grep -q "oauth_session" "$COOKIE_FILE" 2>/dev/null; then
  65. echo -e "${RED}Login succeeded but no session cookie was set.${NC}"
  66. exit 1
  67. fi
  68. echo -e "${GREEN}Login successful. Session cookie saved to ${COOKIE_FILE}${NC}"
  69. # ---------------------------------------------------------------------------
  70. # Step 3: Generate PKCE
  71. # ---------------------------------------------------------------------------
  72. echo -e "${BLUE}=== Step 3: Generate PKCE ===${NC}"
  73. CODE_VERIFIER=$(openssl rand -base64 32 | tr -d '=+/' | cut -c1-128)
  74. CODE_CHALLENGE=$(echo -n "$CODE_VERIFIER" | openssl dgst -sha256 -binary | openssl enc -base64 | tr '+/' '-_' | tr -d '=')
  75. STATE=$(openssl rand -hex 16)
  76. echo -e "${GREEN}Code Verifier:${NC} $CODE_VERIFIER"
  77. echo -e "${GREEN}Code Challenge:${NC} $CODE_CHALLENGE"
  78. echo -e "${GREEN}State:${NC} $STATE"
  79. # ---------------------------------------------------------------------------
  80. # Step 4: Authorize (with auto-consent)
  81. # ---------------------------------------------------------------------------
  82. echo -e "${BLUE}=== Step 4: Authorize ===${NC}"
  83. # First call authorize - it will redirect to consent if needed, or to callback with code
  84. AUTHORIZE_RESPONSE=$(curl -s -G "${BASE_URL}/oauth/authorize" \
  85. -b "$COOKIE_FILE" \
  86. -d "response_type=code" \
  87. -d "client_id=${CLIENT_ID}" \
  88. -d "redirect_uri=${REDIRECT_URI}" \
  89. -d "scope=${SCOPE}" \
  90. -d "code_challenge=${CODE_CHALLENGE}" \
  91. -d "code_challenge_method=S256" \
  92. -d "state=${STATE}" \
  93. -d "consent_given=1" \
  94. -w "\nFINAL_URL:%{redirect_url}" \
  95. -o /dev/null)
  96. FINAL_URL=$(echo "$AUTHORIZE_RESPONSE" | grep "FINAL_URL:" | cut -d':' -f2-)
  97. echo -e "${GREEN}Final redirect URL:${NC} $FINAL_URL"
  98. # Extract authorization code from the final URL
  99. AUTH_CODE=$(echo "$FINAL_URL" | grep -o 'code=[^&]*' | cut -d'=' -f2 || true)
  100. if [ -z "$AUTH_CODE" ]; then
  101. echo -e "${RED}No authorization code found in redirect URL.${NC}"
  102. echo -e "${YELLOW}Full response:${NC}"
  103. echo "$AUTHORIZE_RESPONSE"
  104. exit 1
  105. fi
  106. echo -e "${GREEN}Authorization Code:${NC} $AUTH_CODE"
  107. # ---------------------------------------------------------------------------
  108. # Step 5: Exchange Code for Token
  109. # ---------------------------------------------------------------------------
  110. echo -e "${BLUE}=== Step 5: Exchange Code for Token ===${NC}"
  111. TOKEN_RESPONSE=$(curl -s -X POST "${BASE_URL}/oauth/token" \
  112. -H "Content-Type: application/x-www-form-urlencoded" \
  113. -d "grant_type=authorization_code" \
  114. -d "code=${AUTH_CODE}" \
  115. -d "redirect_uri=${REDIRECT_URI}" \
  116. -d "client_id=${CLIENT_ID}" \
  117. -d "client_secret=${CLIENT_SECRET}" \
  118. -d "code_verifier=${CODE_VERIFIER}")
  119. # Check for errors
  120. if echo "$TOKEN_RESPONSE" | grep -q '"error"'; then
  121. echo -e "${RED}Token exchange failed:${NC}"
  122. echo "$TOKEN_RESPONSE" | python3 -m json.tool 2>/dev/null || echo "$TOKEN_RESPONSE"
  123. exit 1
  124. fi
  125. ACCESS_TOKEN=$(echo "$TOKEN_RESPONSE" | grep -o '"access_token":"[^"]*"' | cut -d'"' -f4)
  126. REFRESH_TOKEN=$(echo "$TOKEN_RESPONSE" | grep -o '"refresh_token":"[^"]*"' | cut -d'"' -f4)
  127. EXPIRES_IN=$(echo "$TOKEN_RESPONSE" | grep -o '"expires_in":[0-9]*' | cut -d':' -f2)
  128. if [ -z "$ACCESS_TOKEN" ]; then
  129. echo -e "${RED}No access token in response.${NC}"
  130. echo "$TOKEN_RESPONSE"
  131. exit 1
  132. fi
  133. # ---------------------------------------------------------------------------
  134. # Output
  135. # ---------------------------------------------------------------------------
  136. echo ""
  137. echo -e "${GREEN}========================================${NC}"
  138. echo -e "${GREEN} SUCCESS! Token obtained${NC}"
  139. echo -e "${GREEN}========================================${NC}"
  140. echo ""
  141. echo -e "${BLUE}Access Token:${NC} ${ACCESS_TOKEN}"
  142. echo -e "${BLUE}Refresh Token:${NC} ${REFRESH_TOKEN}"
  143. echo -e "${BLUE}Expires In:${NC} ${EXPIRES_IN} seconds"
  144. echo ""
  145. echo -e "${YELLOW}Usage example:${NC}"
  146. echo " curl ${BASE_URL}/v1/models -H \"Authorization: Bearer ${ACCESS_TOKEN}\""
  147. echo ""
  148. echo -e "${YELLOW}Environment variables (for reuse):${NC}"
  149. echo " export OAUTH_CLIENT_ID='${CLIENT_ID}'"
  150. echo " export OAUTH_CLIENT_SECRET='${CLIENT_SECRET}'"
  151. echo " export OAUTH_ACCESS_TOKEN='${ACCESS_TOKEN}'"
  152. echo ""
  153. # Optionally save to a file for easy sourcing
  154. TOKEN_FILE="${TOKEN_FILE:-.oauth-token}"
  155. cat > "$TOKEN_FILE" <<EOF
  156. # OAuth 2.1 Token - Generated $(date)
  157. export OAUTH_CLIENT_ID='${CLIENT_ID}'
  158. export OAUTH_CLIENT_SECRET='${CLIENT_SECRET}'
  159. export OAUTH_ACCESS_TOKEN='${ACCESS_TOKEN}'
  160. export OAUTH_REFRESH_TOKEN='${REFRESH_TOKEN}'
  161. EOF
  162. echo -e "${GREEN}Token saved to ${TOKEN_FILE}${NC}"
  163. echo -e "${YELLOW}Source it with:${NC} source ${TOKEN_FILE}"