#!/usr/bin/env bash set -euo pipefail # Get an OAuth 2.1 access token through the full flow: # 1. Register a client (if needed) # 2. Login as admin # 3. Generate PKCE # 4. Authorize with consent # 5. Exchange code for token # 6. Print the access token BASE_URL="${BASE_URL:-http://localhost:3000}" REDIRECT_URI="${REDIRECT_URI:-http://localhost/callback}" ADMIN_EMAIL="${ADMIN_EMAIL:-admin@delete.me}" ADMIN_PASSWORD="${ADMIN_PASSWORD:-deleteme}" SCOPE="${SCOPE:-llm}" COOKIE_FILE="${COOKIE_FILE:-cookies.txt}" # Colors for output GREEN='\033[0;32m' BLUE='\033[0;34m' YELLOW='\033[1;33m' RED='\033[0;31m' NC='\033[0m' # No Color # --------------------------------------------------------------------------- # Step 1: Register a Client # --------------------------------------------------------------------------- echo -e "${BLUE}=== Step 1: Register OAuth Client ===${NC}" REGISTER_RESPONSE=$(curl -s -X POST "${BASE_URL}/oauth/register" \ -H "Content-Type: application/json" \ -d "{ \"client_name\": \"get-token-script\", \"redirect_uris\": [\"${REDIRECT_URI}\"], \"grant_types\": [\"authorization_code\"], \"response_types\": [\"code\"], \"scope\": \"${SCOPE}\", \"token_endpoint_auth_method\": \"client_secret_basic\" }") # Extract client credentials CLIENT_ID=$(echo "$REGISTER_RESPONSE" | grep -o '"client_id":"[^"]*"' | cut -d'"' -f4 || true) CLIENT_SECRET=$(echo "$REGISTER_RESPONSE" | grep -o '"client_secret":"[^"]*"' | cut -d'"' -f4 || true) if [ -z "$CLIENT_ID" ] || [ -z "$CLIENT_SECRET" ]; then echo -e "${RED}Failed to register client. Response:${NC}" echo "$REGISTER_RESPONSE" exit 1 fi echo -e "${GREEN}Client ID:${NC} $CLIENT_ID" echo -e "${GREEN}Client Secret:${NC} $CLIENT_SECRET" # --------------------------------------------------------------------------- # Step 2: Login (Get Session Cookie) # --------------------------------------------------------------------------- echo -e "${BLUE}=== Step 2: Login ===${NC}" # Remove old cookie file if it exists rm -f "$COOKIE_FILE" LOGIN_RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "${BASE_URL}/oauth/login" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "email=${ADMIN_EMAIL}" \ -d "password=${ADMIN_PASSWORD}" \ -c "$COOKIE_FILE" \ -o /dev/null) HTTP_CODE=$(echo "$LOGIN_RESPONSE" | tail -n1) if [ "$HTTP_CODE" != "302" ] && [ "$HTTP_CODE" != "200" ]; then echo -e "${RED}Login failed (HTTP $HTTP_CODE). Check credentials.${NC}" exit 1 fi # Verify cookie was set if ! grep -q "oauth_session" "$COOKIE_FILE" 2>/dev/null; then echo -e "${RED}Login succeeded but no session cookie was set.${NC}" exit 1 fi echo -e "${GREEN}Login successful. Session cookie saved to ${COOKIE_FILE}${NC}" # --------------------------------------------------------------------------- # Step 3: Generate PKCE # --------------------------------------------------------------------------- echo -e "${BLUE}=== Step 3: Generate PKCE ===${NC}" CODE_VERIFIER=$(openssl rand -base64 32 | tr -d '=+/' | cut -c1-128) CODE_CHALLENGE=$(echo -n "$CODE_VERIFIER" | openssl dgst -sha256 -binary | openssl enc -base64 | tr '+/' '-_' | tr -d '=') STATE=$(openssl rand -hex 16) echo -e "${GREEN}Code Verifier:${NC} $CODE_VERIFIER" echo -e "${GREEN}Code Challenge:${NC} $CODE_CHALLENGE" echo -e "${GREEN}State:${NC} $STATE" # --------------------------------------------------------------------------- # Step 4: Authorize (with auto-consent) # --------------------------------------------------------------------------- echo -e "${BLUE}=== Step 4: Authorize ===${NC}" # First call authorize - it will redirect to consent if needed, or to callback with code AUTHORIZE_RESPONSE=$(curl -s -G "${BASE_URL}/oauth/authorize" \ -b "$COOKIE_FILE" \ -d "response_type=code" \ -d "client_id=${CLIENT_ID}" \ -d "redirect_uri=${REDIRECT_URI}" \ -d "scope=${SCOPE}" \ -d "code_challenge=${CODE_CHALLENGE}" \ -d "code_challenge_method=S256" \ -d "state=${STATE}" \ -d "consent_given=1" \ -w "\nFINAL_URL:%{redirect_url}" \ -o /dev/null) FINAL_URL=$(echo "$AUTHORIZE_RESPONSE" | grep "FINAL_URL:" | cut -d':' -f2-) echo -e "${GREEN}Final redirect URL:${NC} $FINAL_URL" # Extract authorization code from the final URL AUTH_CODE=$(echo "$FINAL_URL" | grep -o 'code=[^&]*' | cut -d'=' -f2 || true) if [ -z "$AUTH_CODE" ]; then echo -e "${RED}No authorization code found in redirect URL.${NC}" echo -e "${YELLOW}Full response:${NC}" echo "$AUTHORIZE_RESPONSE" exit 1 fi echo -e "${GREEN}Authorization Code:${NC} $AUTH_CODE" # --------------------------------------------------------------------------- # Step 5: Exchange Code for Token # --------------------------------------------------------------------------- echo -e "${BLUE}=== Step 5: Exchange Code for Token ===${NC}" TOKEN_RESPONSE=$(curl -s -X POST "${BASE_URL}/oauth/token" \ -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}" \ -d "code_verifier=${CODE_VERIFIER}") # Check for errors if echo "$TOKEN_RESPONSE" | grep -q '"error"'; then echo -e "${RED}Token exchange failed:${NC}" echo "$TOKEN_RESPONSE" | python3 -m json.tool 2>/dev/null || echo "$TOKEN_RESPONSE" exit 1 fi ACCESS_TOKEN=$(echo "$TOKEN_RESPONSE" | grep -o '"access_token":"[^"]*"' | cut -d'"' -f4) REFRESH_TOKEN=$(echo "$TOKEN_RESPONSE" | grep -o '"refresh_token":"[^"]*"' | cut -d'"' -f4) EXPIRES_IN=$(echo "$TOKEN_RESPONSE" | grep -o '"expires_in":[0-9]*' | cut -d':' -f2) if [ -z "$ACCESS_TOKEN" ]; then echo -e "${RED}No access token in response.${NC}" echo "$TOKEN_RESPONSE" exit 1 fi # --------------------------------------------------------------------------- # Output # --------------------------------------------------------------------------- echo "" echo -e "${GREEN}========================================${NC}" echo -e "${GREEN} SUCCESS! Token obtained${NC}" echo -e "${GREEN}========================================${NC}" echo "" echo -e "${BLUE}Access Token:${NC} ${ACCESS_TOKEN}" echo -e "${BLUE}Refresh Token:${NC} ${REFRESH_TOKEN}" echo -e "${BLUE}Expires In:${NC} ${EXPIRES_IN} seconds" echo "" echo -e "${YELLOW}Usage example:${NC}" echo " curl ${BASE_URL}/v1/models -H \"Authorization: Bearer ${ACCESS_TOKEN}\"" echo "" echo -e "${YELLOW}Environment variables (for reuse):${NC}" echo " export OAUTH_CLIENT_ID='${CLIENT_ID}'" echo " export OAUTH_CLIENT_SECRET='${CLIENT_SECRET}'" echo " export OAUTH_ACCESS_TOKEN='${ACCESS_TOKEN}'" echo "" # Optionally save to a file for easy sourcing TOKEN_FILE="${TOKEN_FILE:-.oauth-token}" cat > "$TOKEN_FILE" <