Skip to content

feat: add social login and custom Google OAuth commands#445

Merged
moranshe-max merged 7 commits intomainfrom
feat/auth-social-login
Apr 15, 2026
Merged

feat: add social login and custom Google OAuth commands#445
moranshe-max merged 7 commits intomainfrom
feat/auth-social-login

Conversation

@moranshe-max
Copy link
Copy Markdown
Collaborator

@moranshe-max moranshe-max commented Mar 26, 2026

Note

Description

Adds a new base44 auth social-login <provider> <enable|disable> CLI command for managing social login providers (Google, Microsoft, Facebook, Apple). Google additionally supports custom OAuth via --client-id, --client-secret, --client-secret-stdin, and --env-file options to push credentials directly to the backend secrets API. This PR also introduces two reusable utilities — resolveSecret for multi-source secret collection (flag → stdin → env var → interactive prompt) and readStdin for safely reading piped input.

Related Issue

None

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Other (please describe):

Changes Made

  • Added packages/cli/src/cli/commands/auth/social-login.ts: new social-login CLI command with provider/action arguments and Google-specific custom OAuth flags
  • Added packages/cli/src/core/resources/auth-config/social-login.ts: core functions updateSocialLoginConfig and pushCustomOAuthSecret for reading/writing local auth config and pushing secrets to the API
  • Added packages/cli/src/core/resources/auth-config/schema.ts: SOCIAL_PROVIDERS registry and ProviderName type with per-provider schema definitions (toggle field, optional custom OAuth fields)
  • Added packages/cli/src/cli/utils/secret-input.ts: reusable resolveSecret utility with precedence chain (stdin > flag > env var > interactive prompt)
  • Added packages/cli/src/cli/utils/stdin.ts: readStdin utility for safely consuming piped stdin input
  • Wired social-login into the auth command group (auth/index.ts) and exported new utilities from cli/utils/index.ts
  • Refactored password-login.ts to use Commander's Argument.choices() instead of a manual runtime validation function
  • Added comprehensive integration tests (tests/cli/auth_social_login.spec.ts, tests/cli/secret_input.spec.ts) covering argument validation, provider restrictions, happy paths, and custom OAuth flows

Testing

  • I have tested these changes locally
  • I have added/updated tests as needed
  • All tests pass (npm test)

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (if applicable)
  • My changes generate no new warnings
  • I have updated docs/ (AGENTS.md) if I made architectural changes

Additional Notes

The resolveSecret and readStdin utilities are designed for reuse by any future command that needs to accept a secret from multiple input sources (flag, stdin pipe, env var, or interactive prompt). The SOCIAL_PROVIDERS registry in schema.ts makes it straightforward to add new providers or extend Google-style custom OAuth support to other providers in the future.


🤖 Generated by Claude | 2026-04-15 00:00 UTC | 7d24dfc

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 26, 2026

🚀 Package Preview Available!


Install this PR's preview build with npm:

npm i @base44-preview/cli@0.0.50-pr.445.7d24dfc

Prefer not to change any import paths? Install using npm alias so your code still imports base44:

npm i "base44@npm:@base44-preview/cli@0.0.50-pr.445.7d24dfc"

Or add it to your package.json dependencies:

{
  "dependencies": {
    "base44": "npm:@base44-preview/cli@0.0.50-pr.445.7d24dfc"
  }
}

Preview published to npm registry — try new features instantly!

@moranshe-max moranshe-max force-pushed the feat/auth-social-login branch 3 times, most recently from c83a530 to febc3f4 Compare March 31, 2026 12:32
@moranshe-max moranshe-max force-pushed the feat/auth-social-login branch 4 times, most recently from 408fd0a to 8f6207e Compare April 9, 2026 10:37
Comment on lines +45 to +50
.addArgument(
new Argument(
"<action>",
"enable or disable password authentication",
).choices(["enable", "disable"]),
)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

very cool

customOAuth?: CustomOAuthSchema;
}

export const SOCIAL_PROVIDERS: Record<string, SocialProviderSchema> = {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: does it make sense to change the string to a closed provider list?

Copy link
Copy Markdown
Collaborator

@Paveltarno Paveltarno left a comment

Choose a reason for hiding this comment

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

great! added some comments

let clientSecret: string | undefined;

if (useCustomOAuth && oauth) {
clientSecret = await resolveSecret({
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

wdyt about adding an --env-file option as well which will only look for the secret BASE44_GOOGLE_OAUTH_CLIENT_SECRET? I know it's a bit weird but I'm thinking the user would like to just put all their secrets in a .env file (same thing we use for base44 secrets set --env-file)

Comment on lines +85 to +88
/** Environment variable name for the client secret */
envVar: string;
/** Prompt message for interactive secret input */
promptMessage: string;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

these fields should probably not be in /core as they are very CLI oriented

export const SOCIAL_PROVIDERS: Record<string, SocialProviderSchema> = {
google: {
field: "enableGoogleLogin",
label: "Google",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

doesn't bother me that much but this is also a UI concern, maybe we should have a mapping/transformation for the key?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

you mean like capitalize utility that transforms the key to the label?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Added mapping, I prefer the transformation to be explicit.

apple: { field: "enableAppleLogin", label: "Apple" },
};

export const VALID_PROVIDER_NAMES = Object.keys(SOCIAL_PROVIDERS);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

i think also should move to CLI

Comment on lines +133 to +141
.option("--client-id <id>", "custom OAuth client ID (Google only)")
.option(
"--client-secret <secret>",
"custom OAuth client secret (Google only)",
)
.option(
"--client-secret-stdin",
"read client secret from stdin (Google only)",
)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

does it make sense to allow setting only the secret without the clientId? afaiu it will just push a redundant secret?

Comment on lines +134 to +140
.option(
"--client-secret <secret>",
"custom OAuth client secret (Google only)",
)
.option(
"--client-secret-stdin",
"read client secret from stdin (Google only)",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

do you think we should also allow the user to set the client-id only and then let them know that they should push the needed secrets using the base44 secrets set --env-file? again, im thinking of a scenario where i just have an .env file i got from a colleague/vault and i just want to push it once and forget about it


// Hint about pushing secrets separately when client-id was set without a secret
if (useCustomOAuth && !clientSecret) {
outroMessage += `\nRemember to push the client secret separately: base44 secrets set --env-file <path>`;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This hint looks wrong as written. auth social-login ... --env-file reads BASE44_GOOGLE_OAUTH_CLIENT_SECRET and translates it to the backend secret key google_oauth_client_secret, but base44 secrets set --env-file <path> does not do that translation; it uploads keys verbatim from the file. So if the user follows this hint with a .env containing BASE44_GOOGLE_OAUTH_CLIENT_SECRET=..., they will store the wrong remote secret name and custom Google OAuth still will not be configured. I think the follow-up should either point back to auth social-login ... --env-file, or tell the user to set google_oauth_client_secret explicitly.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good catch — fixed. The hint now points to base44 auth social-login <provider> enable --client-id <id> --env-file <path> which handles the key translation to google_oauth_client_secret on the backend.

Copy link
Copy Markdown
Collaborator

@Paveltarno Paveltarno left a comment

Choose a reason for hiding this comment

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

i think i found a small issue, not sure, maybe it's worth adding a test to the explicitly

all other stuff looks great!


// Hint about pushing secrets separately when client-id was set without a secret
if (useCustomOAuth && !clientSecret) {
outroMessage += `\nRemember to push the client secret separately: base44 auth social-login ${provider} enable --client-id ${options.clientId} --env-file <path>`;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for updating the hint. I think I meant something slightly different in my previous comment. My concern is not only what command we suggest here, but that I do want users to be able to put this secret in a .env file and then use base44 secrets set --env-file ... as a valid workflow. That still does not work cleanly today, because auth social-login --env-file reads BASE44_GOOGLE_OAUTH_CLIENT_SECRET, while secrets set --env-file uploads keys verbatim and the backend secret name is google_oauth_client_secret. So users still cannot reuse the same .env shape with secrets set --env-file unless they know the internal secret key name. I think the fix I had in mind is to standardize the .env file key for this flow on the backend secret name (google_oauth_client_secret) and update the command/help/tests accordingly.

Copy link
Copy Markdown
Collaborator Author

@moranshe-max moranshe-max Apr 13, 2026

Choose a reason for hiding this comment

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

Got it. Misunderstood you.
The reason I added the BASE44 prefix is just to make sure it's not being confused with other env vars since google_oauth_client_secret is a pretty generic name. but maybe it's not a real concern?

@moranshe-max moranshe-max force-pushed the feat/auth-social-login branch from 1867ac0 to 071d526 Compare April 15, 2026 11:17
@moranshe-max moranshe-max requested a review from Paveltarno April 15, 2026 12:06
moranshe-max and others added 7 commits April 15, 2026 16:18
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move CLI-oriented fields (labels, env vars, prompt messages,
VALID_PROVIDER_NAMES) from core/schema.ts to CLI layer. Add --env-file
option for reading client secret from a .env file. Require --client-id
when secret options are provided. Allow --client-id only and hint about
pushing secrets via `base44 secrets set --env-file`.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The previous hint pointed to `secrets set --env-file` which uploads keys
verbatim, but the backend expects `google_oauth_client_secret` not the
env var name. Point to `auth social-login --env-file` instead which
handles the key translation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Match the env-file key convention by using google_oauth_client_secret
instead of BASE44_GOOGLE_OAUTH_CLIENT_SECRET.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@moranshe-max moranshe-max force-pushed the feat/auth-social-login branch from ead6556 to 823e5ec Compare April 15, 2026 13:18
Copy link
Copy Markdown
Collaborator

@Paveltarno Paveltarno left a comment

Choose a reason for hiding this comment

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

🔥

@moranshe-max moranshe-max merged commit d593982 into main Apr 15, 2026
14 checks passed
@moranshe-max moranshe-max deleted the feat/auth-social-login branch April 15, 2026 13:56
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.

2 participants