Visitar URL original
feat: add OAUTH_USERINFO fallback for providers with opaque tokens by SPAutomation7 · Pull Request #1425 · dbgate/dbgate · GitHub
Skip to content

feat: add OAUTH_USERINFO fallback for providers with opaque tokens - #1425

Open
SPAutomation7 wants to merge 12 commits into
dbgate:masterfrom
Automya:feat/oauth-userinfo
Open

SPAutomation7 wants to merge 12 commits into
dbgate:masterfrom
Automya:feat/oauth-userinfo

Conversation

@SPAutomation7

Copy link
Copy Markdown

Fixes #1424

Problem

GitHub OAuth (and similar providers like Bitbucket, GitLab CE) return opaque access tokens instead of JWTs, and don't provide an id_token. This means both existing decode attempts in oauthToken() return null, the login defaults to the literal string 'oauth', and authentication fails with "Username oauth not allowed to log in".

Additionally, GitHub's token endpoint returns application/x-www-form-urlencoded by default, so without an explicit Accept: application/json header the response isn't parsed correctly.

Changes

packages/api/src/auth/authProvider.js:

  1. Added Accept: application/json header to the token exchange POST request (ensures proper JSON parsing for all providers, backwards compatible)

  2. Added a third fallback after the existing JWT decode attempts: if OAUTH_USERINFO env var is set and both access_token and id_token JWT decoding failed, fetch user info from the configured endpoint using the Bearer token:

if (!payload && process.env.OAUTH_USERINFO) {
  const userResp = await axios.default.get(process.env.OAUTH_USERINFO, {
    headers: { Authorization: `Bearer ${access_token}`, Accept: 'application/json' },
  });
  payload = userResp.data;
}

Backwards compatibility

  • The Accept: application/json header is standard and already expected by all major OAuth providers. No behavioral change for existing setups.
  • The OAUTH_USERINFO fallback is opt-in. If the env var is not set, the code path is never reached. Existing deployments are unaffected.

Testing

Tested with GitHub OAuth in a self-hosted Docker deployment:

  • OAUTH_USERINFO=https://api.github.com/user
  • OAUTH_LOGIN_FIELD=login
  • Users authenticate via GitHub, login field is correctly extracted from the userinfo response, OAUTH_ALLOWED_LOGINS and LOGIN_PERMISSIONS_* work as expected.

GitHub OAuth returns opaque access tokens (not JWTs) and has no id_token.
This adds a third fallback that fetches user info from a configurable
endpoint (e.g. https://api.github.com/user) using the Bearer token.

Also adds Accept: application/json header to the token request, since
GitHub's token endpoint returns application/x-www-form-urlencoded by
default unless explicitly asked for JSON.

Fixes compatibility with GitHub OAuth and similar providers.
Copilot AI review requested due to automatic review settings April 10, 2026 16:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves OAuth login in the API by supporting providers that return opaque access tokens (e.g., GitHub) and ensuring token exchange responses are parsed as JSON.

Changes:

  • Add Accept: application/json to the OAuth token exchange request to avoid form-encoded responses breaking parsing.
  • Add an opt-in OAUTH_USERINFO fallback to fetch a user profile when JWT decoding of tokens fails.
  • Add a GitHub Actions workflow to build and push a custom Docker image to an AWS ECR registry.

Reviewed changes

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

File Description
packages/api/src/auth/authProvider.js Adds JSON accept header for token exchange and an opt-in userinfo fetch fallback for opaque-token providers.
.github/workflows/build-custom-docker.yaml Introduces a custom Docker build-and-push workflow targeting a specific ECR registry/repository.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/api/src/auth/authProvider.js Outdated
POSIX shells (sh/dash) silently drop environment variables whose names
contain hyphens because they are not valid shell identifiers. This caused
LOGIN_PERMISSIONS_* vars for GitHub users with hyphens in their username
(e.g. adrian-da-silva) to never reach the Node.js process.

Switching from entrypoint.sh to a direct CMD bypasses the shell, so
Node.js receives ALL env vars set by Kubernetes.
…okup

POSIX shells and K8s envFrom both reject env var names containing
hyphens. Instead of fighting this, normalize GitHub usernames by
replacing hyphens with underscores when constructing the env var key.

This allows LOGIN_PERMISSIONS_adrian_da_silva to match the GitHub
user adrian-da-silva.
Without adjustPackageJson, useBundleExternals stays 'false' and webpack
externalizes ALL plugin dependencies (lodash, dbgate-tools, etc).
These never get installed in the Docker image, causing:
  Cannot find module 'lodash' when loading dbgate-plugin-postgres

adjustPackageJson sets useBundleExternals='true' so non-volatile deps
get bundled INTO the plugin backend.js files.
- Remove debug logging from authProvider.js
- Remove Automya-specific CI workflow
- Restore original Dockerfile
- Add comment explaining hyphen-to-underscore normalization
@adrian-da-silva

Copy link
Copy Markdown

Updated PR — cleaned up and added hyphen normalization fix

Changes in packages/api/src/auth/authProvider.js:

  1. Accept: application/json header on OAuth token exchange — some providers (GitHub) return form-encoded data without this header.

  2. OAUTH_USERINFO fallback — when both access_token and id_token fail JWT decoding (opaque tokens, e.g. GitHub), fetch the user profile from the configured userinfo endpoint. Opt-in via OAUTH_USERINFO env var.

  3. Hyphen-to-underscore normalization in getCurrentPermissions() — converts hyphens to underscores when building the LOGIN_PERMISSIONS_<login> env var key. This is needed because env var names with hyphens are invalid in POSIX shells and silently skipped by Kubernetes envFrom. For example, login my-user maps to LOGIN_PERMISSIONS_my_user.

GitHub OAuth configuration example

OAUTH_AUTH=https://github.com/login/oauth/authorize
OAUTH_TOKEN=https://github.com/login/oauth/access_token
OAUTH_CLIENT_ID=<your-client-id>
OAUTH_CLIENT_SECRET=<your-client-secret>
OAUTH_LOGIN_FIELD=login
OAUTH_SCOPE=read:user
OAUTH_USERINFO=https://api.github.com/user

For per-user permissions with hyphenated usernames, use underscores:

LOGIN_PERMISSIONS_my_user="~*,widgets/database,dbops/query,connections/myconn"

Previous commits with debug logging and Automya-specific CI have been cleaned up. The diff now only touches authProvider.js.

adrian-da-silva and others added 3 commits July 8, 2026 10:53
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Restores .github/workflows/build-custom-docker.yaml, removed in 865b71f
while cleaning the branch for upstream review, and builds each architecture
on its own native runner.

The removal had a cost: the manual rebuild that replaced it (image tag
oauth-userinfo-multiplatform, 2026-09-10) left out `adjustPackageJson
--community`, so common/useBundleExternals.js stayed 'false', plugin
webpack treated lodash and dbgate-tools as externals instead of bundling
them, and docker/package.json was generated without the driver deps.
Every connection in staging then failed with a misleading
"Cannot find module '.../dbgate-plugin-postgres/dist/backend.js'" -- the
file is there; the require that actually fails is lodash. That step had
already been added in b2a32ad five hours before the workflow was deleted.

Changes over the April version:
- matrix of native runners (ubuntu-24.04 / ubuntu-24.04-arm), each running
  its own prep. docker/Dockerfile does not run yarn install: prepare:docker
  vendors node_modules from the host, so a single-runner cross build ships
  one architecture's native modules inside the other's image. yarn also
  resolves optionalDependencies per platform, so the wrong package gets
  installed, not just the wrong binary.
- push by digest, then a merge job builds the manifest list.
- publishes oauth-userinfo-v2 and oauth-userinfo-<short-sha>. The
  oauth-userinfo tag is left alone: it is what production runs.
- sanity check that fails the run when the prepared build has too few
  modules or a too-small plugin backend.js.

Verified locally for both architectures: 185 packages in
docker/node_modules, 127922-byte dbgate-plugin-postgres/dist/backend.js,
per-platform native bindings, and both slices connecting to a live
postgres:16 (server-status ok, databases listed).
ci: build multi-arch image on native runners

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GitHub OAuth login fails - "Username oauth not allowed to log in"

4 participants