Skip to content

fix: convert Custom OAuth handshake failures to handled Meteor.Errors to prevent 500 crash (fixes #35649)#39391

Open
kushkumarkashyap7280 wants to merge 3 commits into
RocketChat:developfrom
kushkumarkashyap7280:fix/35649-custom-oauth-login-500-error
Open

fix: convert Custom OAuth handshake failures to handled Meteor.Errors to prevent 500 crash (fixes #35649)#39391
kushkumarkashyap7280 wants to merge 3 commits into
RocketChat:developfrom
kushkumarkashyap7280:fix/35649-custom-oauth-login-500-error

Conversation

@kushkumarkashyap7280
Copy link
Copy Markdown

@kushkumarkashyap7280 kushkumarkashyap7280 commented Mar 5, 2026

Proposed changes

This PR resolves an Internal Server Error (500) that occurs during the Custom OAuth login flow via the REST API.

The issue was caused by the use of generic Error objects and unhandled promise rejections in the OAuth login handler. When an invalid token or a connection failure occurred, the server threw a standard JavaScript Error, which the API middleware interprets as a 500 status.

screenshot :
Screenshot From 2026-03-06 00-19-01

Key Changes:

Refactored Accounts.registerLoginHandler in oauth.js to catch errors during handleAccessTokenRequest.

Replaced generic Error and Accounts.ConfigError with Meteor.Error to ensure the API returns a structured 401 Unauthorized or 400 Bad Request response.

Added specific error codes (error-invalid-service, error-service-not-configured) for better client-side debugging.

Issue(s)

Closes #35649

Steps to test or reproduce

Enable Custom OAuth in Settings and point it to a non-existent URL (e.g., http://localhost:9999).

Attempt to login via REST API:

Bash
curl -X POST http://localhost:3000/api/v1/login
-H "Content-Type: application/json"
-d '{ "serviceName": "bugHunt", "accessToken": "test", "expiresIn": 3600 }'
Expected Behavior (Fixed): Returns 401 Unauthorized with {"success":false,"error":"error-invalid-access-token"}.

Actual Behavior (Before): Returns 500 Internal Server Error.

Further comments

I chose to wrap the service.handleAccessTokenRequest in a try/catch block because this is the primary point of failure for network-related OAuth handshakes. By returning a Meteor.Error here, we provide a consistent error interface for all OAuth providers, not just custom ones.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed Custom OAuth login flow to return appropriate HTTP error codes (401/400) when authentication handshake fails, instead of displaying a generic 500 Internal Server Error. Improved error handling for invalid services, non-configured services, and invalid access tokens to provide clearer feedback during authentication failures.

@dionisio-bot
Copy link
Copy Markdown
Contributor

dionisio-bot Bot commented Mar 5, 2026

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is missing the 'stat: QA assured' label
  • This PR is missing the required milestone or project

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Mar 5, 2026

🦋 Changeset detected

Latest commit: 9b89833

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 41 packages
Name Type
@rocket.chat/meteor Patch
@rocket.chat/core-typings Patch
@rocket.chat/rest-typings Patch
@rocket.chat/uikit-playground Patch
@rocket.chat/api-client Patch
@rocket.chat/apps Patch
@rocket.chat/core-services Patch
@rocket.chat/cron Patch
@rocket.chat/ddp-client Patch
@rocket.chat/fuselage-ui-kit Patch
@rocket.chat/gazzodown Patch
@rocket.chat/http-router Patch
@rocket.chat/livechat Patch
@rocket.chat/model-typings Patch
@rocket.chat/ui-avatar Patch
@rocket.chat/ui-client Patch
@rocket.chat/ui-contexts Patch
@rocket.chat/ui-voip Patch
@rocket.chat/web-ui-registration Patch
@rocket.chat/account-service Patch
@rocket.chat/authorization-service Patch
@rocket.chat/ddp-streamer Patch
@rocket.chat/omnichannel-transcript Patch
@rocket.chat/presence-service Patch
@rocket.chat/queue-worker Patch
@rocket.chat/abac Patch
@rocket.chat/federation-matrix Patch
@rocket.chat/license Patch
@rocket.chat/media-calls Patch
@rocket.chat/omnichannel-services Patch
@rocket.chat/pdf-worker Patch
@rocket.chat/presence Patch
rocketchat-services Patch
@rocket.chat/models Patch
@rocket.chat/network-broker Patch
@rocket.chat/omni-core-ee Patch
@rocket.chat/mock-providers Patch
@rocket.chat/ui-video-conf Patch
@rocket.chat/instance-status Patch
@rocket.chat/omni-core Patch
@rocket.chat/server-fetch Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 5, 2026

Walkthrough

A patch release fix for Custom OAuth login error handling. The changes modify the OAuth token validation flow to throw proper Meteor.Error exceptions with appropriate HTTP status codes (401/400) instead of returning generic 500 Internal Server Errors when authentication handshakes fail.

Changes

Cohort / File(s) Summary
Release Documentation
.changeset/six-forks-remain.md
Changelog entry documenting the OAuth bug fix for patch release of @rocket.chat/meteor.
OAuth Error Handling
apps/meteor/app/lib/server/oauth/oauth.js
Improved error handling in OAuth login flow: replaced generic errors with Meteor.Error for invalid service and access token scenarios; added service configuration validation; wrapped handleAccessTokenRequest in try-catch to properly throw errors with appropriate HTTP status codes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested labels

type: bug, area: authentication

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: converting Custom OAuth handshake failures to Meteor.Errors to prevent 500 crashes, which directly matches the changeset modifications.
Linked Issues check ✅ Passed The PR successfully addresses all coding objectives from #35649: replacing generic errors with Meteor.Error, validating service configuration, handling access token request failures, and returning proper 401/400 status codes.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the Custom OAuth login error handling issue; no unrelated modifications were introduced outside the stated objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 1 file

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
apps/meteor/app/lib/server/oauth/oauth.js (1)

54-59: Consider preserving error context for different failure modes.

The catch block converts all errors to error-invalid-access-token, but the underlying handleAccessTokenRequest can fail for distinct reasons: network failures, OAuth provider 5xx errors, token validation failures, or JSON parsing errors. Conflating these may complicate debugging for integrators.

A potential improvement would be to differentiate error codes based on failure type, or at minimum preserve the original error as the cause:

♻️ Optional: Preserve error context
 	let oauthResult;
 	try {
 		oauthResult = await service.handleAccessTokenRequest(options);
 	} catch (err) {
-		throw new Meteor.Error('error-invalid-access-token', err.message);
+		throw new Meteor.Error('error-invalid-access-token', err.message, { cause: err });
 	}

That said, the current implementation achieves the PR's goal of preventing 500 errors while returning actionable error messages.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/app/lib/server/oauth/oauth.js` around lines 54 - 59, The catch
currently maps every failure from service.handleAccessTokenRequest to
'error-invalid-access-token', losing failure context; update the catch to
inspect the thrown error (e.g., err.name, err.statusCode, or err.code) and map
to more specific Meteor.Error codes for network/provider/validation/parsing
failures (or at minimum include the original error as the cause/detail), then
rethrow a Meteor.Error that includes that specific code and the original error
message/stack in its details so callers can distinguish failure modes while
preserving the existing non-500 behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/meteor/app/lib/server/oauth/oauth.js`:
- Around line 54-59: The catch currently maps every failure from
service.handleAccessTokenRequest to 'error-invalid-access-token', losing failure
context; update the catch to inspect the thrown error (e.g., err.name,
err.statusCode, or err.code) and map to more specific Meteor.Error codes for
network/provider/validation/parsing failures (or at minimum include the original
error as the cause/detail), then rethrow a Meteor.Error that includes that
specific code and the original error message/stack in its details so callers can
distinguish failure modes while preserving the existing non-500 behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d42e518a-8d00-474f-ace6-38e304d48256

📥 Commits

Reviewing files that changed from the base of the PR and between 819399c and 7a8dac1.

📒 Files selected for processing (2)
  • .changeset/six-forks-remain.md
  • apps/meteor/app/lib/server/oauth/oauth.js
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/app/lib/server/oauth/oauth.js
🧠 Learnings (4)
📚 Learning: 2026-02-24T19:09:09.561Z
Learnt from: ahmed-n-abdeltwab
Repo: RocketChat/Rocket.Chat PR: 38974
File: apps/meteor/app/api/server/v1/im.ts:220-221
Timestamp: 2026-02-24T19:09:09.561Z
Learning: In RocketChat/Rocket.Chat OpenAPI migration PRs for apps/meteor/app/api/server/v1 endpoints, maintainers prefer to avoid any logic changes; style-only cleanups (like removing inline comments) may be deferred to follow-ups to keep scope tight.

Applied to files:

  • .changeset/six-forks-remain.md
📚 Learning: 2026-02-24T19:05:56.710Z
Learnt from: ahmed-n-abdeltwab
Repo: RocketChat/Rocket.Chat PR: 0
File: :0-0
Timestamp: 2026-02-24T19:05:56.710Z
Learning: Rocket.Chat repo context: When a workspace manifest on develop already pins a dependency version (e.g., packages/web-ui-registration → "rocket.chat/ui-contexts": "27.0.1"), a lockfile change in a feature PR that upgrades only that dependency’s resolution is considered a manifest-driven sync and can be kept, preferably as a small "chore: sync yarn.lock with manifests" commit.

Applied to files:

  • .changeset/six-forks-remain.md
📚 Learning: 2026-02-25T20:10:16.987Z
Learnt from: ahmed-n-abdeltwab
Repo: RocketChat/Rocket.Chat PR: 38913
File: packages/ddp-client/src/legacy/types/SDKLegacy.ts:34-34
Timestamp: 2026-02-25T20:10:16.987Z
Learning: In the RocketChat/Rocket.Chat monorepo, packages/ddp-client and apps/meteor do not use TypeScript project references. Module augmentations in apps/meteor (e.g., declare module 'rocket.chat/rest-typings') are not visible when compiling packages/ddp-client in isolation, which is why legacy SDK methods that depend on OperationResult types for OpenAPI-migrated endpoints must remain commented out.

Applied to files:

  • .changeset/six-forks-remain.md
📚 Learning: 2026-01-17T01:51:47.764Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38219
File: packages/core-typings/src/cloud/Announcement.ts:5-6
Timestamp: 2026-01-17T01:51:47.764Z
Learning: In packages/core-typings/src/cloud/Announcement.ts, the AnnouncementSchema.createdBy field intentionally overrides IBannerSchema.createdBy (object with _id and optional username) with a string enum ['cloud', 'system'] to match existing runtime behavior. This is documented as technical debt with a FIXME comment at apps/meteor/app/cloud/server/functions/syncWorkspace/handleCommsSync.ts:53 and should not be flagged as an error until the runtime behavior is corrected.

Applied to files:

  • .changeset/six-forks-remain.md
🔇 Additional comments (4)
.changeset/six-forks-remain.md (1)

1-5: LGTM!

The changeset accurately documents the bug fix with the appropriate patch semver level. The description clearly communicates the behavior change from 500 to proper 401/400 error responses.

apps/meteor/app/lib/server/oauth/oauth.js (3)

33-35: LGTM!

Good change to use Meteor.Error with a specific error code instead of a generic Error. This ensures the API middleware can return a structured response instead of a 500.


37-41: LGTM!

The explicit service configuration check with a descriptive Meteor.Error is a good addition. This provides clear feedback when the OAuth service isn't properly configured.


43-52: LGTM!

Good defensive check ensuring the service is registered with Meteor's OAuth system. Returning an error object (rather than throwing) follows Meteor's registerLoginHandler convention for authentication failures.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Internal Server Error when Logging in with Custom OAuth Token

1 participant