From adobe-pack
Configures Adobe OAuth and API access (Firefly, Photoshop) across dev, staging, prod using separate Developer Console projects, env-specific scopes, and secret managers (AWS, GCP, Vault).
npx claudepluginhub jeremylongshore/claude-code-plugins-plus-skills --plugin adobe-packThis skill is limited to using the following tools:
Configure Adobe APIs across development, staging, and production environments using separate Developer Console projects, environment-specific OAuth credentials, and cloud-native secret management.
Installs and configures Adobe OAuth Server-to-Server credentials; sets up SDKs for Firefly Services, PDF Services, I/O Runtime in Node.js or Python.
Configures Canva Connect API across dev, staging, prod with per-environment OAuth credentials, redirect URIs, and TypeScript config loader. For multi-env Canva deployments.
Configures Apollo.io multi-environment setups (dev, staging, prod) with Zod schemas for API keys, rate limits, features, and Kubernetes secrets.
Share bugs, ideas, or general feedback.
Configure Adobe APIs across development, staging, and production environments using separate Developer Console projects, environment-specific OAuth credentials, and cloud-native secret management.
Adobe best practice: one Developer Console project per environment with separate OAuth credentials.
| Environment | Console Project | Scopes | Product Profile |
|---|---|---|---|
| Development | my-app-dev | openid,AdobeID | Dev sandbox |
| Staging | my-app-staging | openid,AdobeID,firefly_api | Staging profile |
| Production | my-app-prod | openid,AdobeID,firefly_api,ff_apis | Production profile |
// src/config/adobe.ts
interface AdobeEnvConfig {
imsEndpoint: string; // Same across all envs
fireflyEndpoint: string; // Same across all envs
photoshopEndpoint: string; // Same across all envs
scopes: string; // Different per env (least privilege)
retries: number;
timeoutMs: number;
cache: { enabled: boolean; ttlMs: number };
}
const configs: Record<string, AdobeEnvConfig> = {
development: {
imsEndpoint: 'https://ims-na1.adobelogin.com',
fireflyEndpoint: 'https://firefly-api.adobe.io',
photoshopEndpoint: 'https://image.adobe.io',
scopes: 'openid,AdobeID', // Minimal scopes for dev
retries: 1, // Fast failure in dev
timeoutMs: 15_000,
cache: { enabled: false, ttlMs: 0 }, // No cache in dev
},
staging: {
imsEndpoint: 'https://ims-na1.adobelogin.com',
fireflyEndpoint: 'https://firefly-api.adobe.io',
photoshopEndpoint: 'https://image.adobe.io',
scopes: 'openid,AdobeID,firefly_api',
retries: 3,
timeoutMs: 30_000,
cache: { enabled: true, ttlMs: 60_000 },
},
production: {
imsEndpoint: 'https://ims-na1.adobelogin.com',
fireflyEndpoint: 'https://firefly-api.adobe.io',
photoshopEndpoint: 'https://image.adobe.io',
scopes: 'openid,AdobeID,firefly_api,ff_apis',
retries: 5,
timeoutMs: 60_000,
cache: { enabled: true, ttlMs: 300_000 },
},
};
export function getAdobeConfig(): AdobeEnvConfig & { clientId: string; clientSecret: string } {
const env = process.env.NODE_ENV || 'development';
const config = configs[env] || configs.development;
return {
...config,
clientId: process.env.ADOBE_CLIENT_ID!,
clientSecret: process.env.ADOBE_CLIENT_SECRET!,
};
}
# --- Local Development ---
# .env.local (git-ignored)
ADOBE_CLIENT_ID=dev-client-id-from-console
ADOBE_CLIENT_SECRET=p8_dev_secret
ADOBE_SCOPES=openid,AdobeID
# --- GCP Secret Manager ---
# Create secrets for staging and production
gcloud secrets create adobe-client-id-staging --data-file=- <<< "staging-client-id"
gcloud secrets create adobe-client-secret-staging --data-file=- <<< "p8_staging_secret"
gcloud secrets create adobe-client-id-prod --data-file=- <<< "prod-client-id"
gcloud secrets create adobe-client-secret-prod --data-file=- <<< "p8_prod_secret"
# Grant service account access
gcloud secrets add-iam-policy-binding adobe-client-secret-prod \
--member="serviceAccount:my-app@project.iam.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
# --- AWS Secrets Manager ---
aws secretsmanager create-secret \
--name adobe/staging/credentials \
--secret-string '{"client_id":"...","client_secret":"p8_staging_..."}'
aws secretsmanager create-secret \
--name adobe/production/credentials \
--secret-string '{"client_id":"...","client_secret":"p8_prod_..."}'
# --- HashiCorp Vault ---
vault kv put secret/adobe/staging client_id="..." client_secret="p8_staging_..."
vault kv put secret/adobe/production client_id="..." client_secret="p8_prod_..."
# .github/workflows/deploy.yml
jobs:
deploy:
strategy:
matrix:
environment: [staging, production]
environment: ${{ matrix.environment }}
runs-on: ubuntu-latest
env:
NODE_ENV: ${{ matrix.environment }}
ADOBE_CLIENT_ID: ${{ secrets[format('ADOBE_CLIENT_ID_{0}', matrix.environment)] }}
ADOBE_CLIENT_SECRET: ${{ secrets[format('ADOBE_CLIENT_SECRET_{0}', matrix.environment)] }}
steps:
- uses: actions/checkout@v4
- run: npm ci && npm test
- name: Verify Adobe credentials for ${{ matrix.environment }}
run: |
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST \
'https://ims-na1.adobelogin.com/ims/token/v3' \
-d "client_id=${ADOBE_CLIENT_ID}&client_secret=${ADOBE_CLIENT_SECRET}&grant_type=client_credentials&scope=openid,AdobeID")
if [ "$HTTP_CODE" != "200" ]; then
echo "::error::Adobe credential validation failed for ${{ matrix.environment }}"
exit 1
fi
- run: npm run deploy:${{ matrix.environment }}
// Prevent accidental production operations in non-prod
function requireEnvironment(required: string): void {
const current = process.env.NODE_ENV || 'development';
if (current !== required) {
throw new Error(
`Operation requires ${required} environment, currently running in ${current}`
);
}
}
// Usage: guard dangerous operations
async function deleteAllCachedAssets() {
requireEnvironment('production');
// ... actual deletion logic
}
| Issue | Cause | Solution |
|---|---|---|
invalid_scope in staging | Scope not in staging project | Add API to staging Console project |
| Wrong credentials deployed | Environment mismatch | Verify NODE_ENV matches secret path |
| Secret access denied | Missing IAM binding | Grant secretAccessor role |
| Config merge fails | Missing env config file | Ensure all environments defined |
For observability setup, see adobe-observability.