From 78a8272cd19c28e76ae653e68e93a12d0b578eb1 Mon Sep 17 00:00:00 2001
From: Carl Kittelberger <icedream@icedream.pw>
Date: Thu, 23 Sep 2021 13:49:58 +0200
Subject: [PATCH] feat(composer): bearer token authentication (#6901) (#11856)

Co-authored-by: Rhys Arkins <rhys@arkins.net>
---
 docs/usage/php.md                                | 16 ++++++++++++++--
 .../__snapshots__/artifacts.spec.ts.snap         |  2 +-
 lib/manager/composer/artifacts.spec.ts           |  5 +++++
 lib/manager/composer/artifacts.ts                |  5 ++++-
 lib/manager/composer/types.ts                    |  1 +
 5 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/docs/usage/php.md b/docs/usage/php.md
index 5634e6adc7..426fa420b4 100644
--- a/docs/usage/php.md
+++ b/docs/usage/php.md
@@ -31,6 +31,11 @@ If you are using a [privately hosted Composer package](https://getcomposer.org/d
       "hostType": "packagist",
       "username": "<your-username>",
       "password": "<your-password>"
+    },
+    {
+      "matchHost": "bearer-auth.for.vendor.com",
+      "hostType": "packagist",
+      "token": "abcdef0123456789"
     }
   ]
 }
@@ -49,8 +54,15 @@ You may encrypt your `password` only, but you can encrypt your `username` as wel
       "matchHost": "some.vendor.com",
       "hostType": "packagist",
       "encrypted": {
-        "username": "<your-encrypted-password",
-        "password": "<your-encrypted-password"
+        "username": "<your-encrypted-password>",
+        "password": "<your-encrypted-password>"
+      }
+    },
+    {
+      "matchHost": "bearer-auth.for.vendor.com",
+      "hostType": "packagist",
+      "encrypted": {
+        "token": "<your-encrypted-token>"
       }
     }
   ]
diff --git a/lib/manager/composer/__snapshots__/artifacts.spec.ts.snap b/lib/manager/composer/__snapshots__/artifacts.spec.ts.snap
index c9f2c54c08..faf3075dd2 100644
--- a/lib/manager/composer/__snapshots__/artifacts.spec.ts.snap
+++ b/lib/manager/composer/__snapshots__/artifacts.spec.ts.snap
@@ -234,7 +234,7 @@ Array [
       "cwd": "/tmp/github/some/repo",
       "encoding": "utf-8",
       "env": Object {
-        "COMPOSER_AUTH": "{\\"github-oauth\\":{\\"github.com\\":\\"github-token\\"},\\"gitlab-token\\":{\\"gitlab.com\\":\\"gitlab-token\\"},\\"gitlab-domains\\":[\\"gitlab.com\\"],\\"http-basic\\":{\\"packagist.renovatebot.com\\":{\\"username\\":\\"some-username\\",\\"password\\":\\"some-password\\"},\\"artifactory.yyyyyyy.com\\":{\\"username\\":\\"some-other-username\\",\\"password\\":\\"some-other-password\\"}}}",
+        "COMPOSER_AUTH": "{\\"github-oauth\\":{\\"github.com\\":\\"github-token\\"},\\"gitlab-token\\":{\\"gitlab.com\\":\\"gitlab-token\\"},\\"gitlab-domains\\":[\\"gitlab.com\\"],\\"http-basic\\":{\\"packagist.renovatebot.com\\":{\\"username\\":\\"some-username\\",\\"password\\":\\"some-password\\"},\\"artifactory.yyyyyyy.com\\":{\\"username\\":\\"some-other-username\\",\\"password\\":\\"some-other-password\\"}},\\"bearer\\":{\\"packages-bearer.example.com\\":\\"abcdef0123456789\\"}}",
         "COMPOSER_CACHE_DIR": "/tmp/renovate/cache/others/composer",
         "HOME": "/home/user",
         "HTTPS_PROXY": "https://example.com",
diff --git a/lib/manager/composer/artifacts.spec.ts b/lib/manager/composer/artifacts.spec.ts
index c8d8f13b76..0f168ff823 100644
--- a/lib/manager/composer/artifacts.spec.ts
+++ b/lib/manager/composer/artifacts.spec.ts
@@ -123,6 +123,11 @@ describe('manager/composer/artifacts', () => {
       username: 'some-other-username',
       password: 'some-other-password',
     });
+    hostRules.add({
+      hostType: datasourcePackagist.id,
+      matchHost: 'https://packages-bearer.example.com/',
+      token: 'abcdef0123456789',
+    });
     fs.readLocalFile.mockResolvedValueOnce('{}');
     const execSnapshots = mockExecAll(exec);
     fs.readLocalFile.mockResolvedValueOnce('{}');
diff --git a/lib/manager/composer/artifacts.ts b/lib/manager/composer/artifacts.ts
index 17320ab165..916cde6b32 100644
--- a/lib/manager/composer/artifacts.ts
+++ b/lib/manager/composer/artifacts.ts
@@ -63,10 +63,13 @@ function getAuthJson(): string | null {
   hostRules
     .findAll({ hostType: datasourcePackagist.id })
     ?.forEach((hostRule) => {
-      const { resolvedHost, username, password } = hostRule;
+      const { resolvedHost, username, password, token } = hostRule;
       if (resolvedHost && username && password) {
         authJson['http-basic'] = authJson['http-basic'] || {};
         authJson['http-basic'][resolvedHost] = { username, password };
+      } else if (resolvedHost && token) {
+        authJson.bearer = authJson.bearer || {};
+        authJson.bearer[resolvedHost] = token;
       }
     });
 
diff --git a/lib/manager/composer/types.ts b/lib/manager/composer/types.ts
index 3e34fe8604..b5df7f99c1 100644
--- a/lib/manager/composer/types.ts
+++ b/lib/manager/composer/types.ts
@@ -41,6 +41,7 @@ export interface UserPass {
 }
 
 export interface AuthJson {
+  bearer?: Record<string, string>;
   'github-oauth'?: Record<string, string>;
   'gitlab-token'?: Record<string, string>;
   'gitlab-domains'?: string[];
-- 
GitLab