Skip to content

feat(core): support custom userInfo functions in OAuth providers#182

Merged
halvaradop merged 2 commits into
masterfrom
feat/add-custom-userinfo-function
Jun 8, 2026
Merged

feat(core): support custom userInfo functions in OAuth providers#182
halvaradop merged 2 commits into
masterfrom
feat/add-custom-userinfo-function

Conversation

@halvaradop

@halvaradop halvaradop commented Jun 8, 2026

Copy link
Copy Markdown
Member

Description

This pull request adds support for custom userInfo request functions in OAuth providers, allowing developers to fully customize how user information is retrieved from the provider.

With this feature, Aura Auth continues to manage the OAuth flow, token exchange, and token context, while developers can implement their own logic for fetching and mapping user profile data. This provides greater flexibility for providers that require custom request headers, response transformations, or non-standard user information endpoints.

Usage

import type { OAuthProviderConfig } from "@aura-stack/auth/types"

export const provider: OAuthProviderConfig = {
  // ...
  userInfo: {
    url: "https://example.com/oauth/userinfo",
    request: async (ctx) => {
      const response = await fetch(ctx.userInfoURL, {
        method: "GET",
        headers: {
          "User-Agent": `Aura Auth/${AURA_AUTH_VERSION}`,
        },
      })

      const json = await response.json()

      return {
        sub: ctx.accessToken,
        name: json.name,
        email: json.email,
        image: "http://example.com/john-doe.jpg",
      }
    },
  },
}

Benefits

  • Full control over user information requests
  • Custom request headers and fetch options
  • Support for non-standard OAuth providers
  • Custom user profile mapping and transformations
  • Aura Auth continues to handle token exchange and OAuth context management

@vercel

vercel Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
auth Skipped Skipped Jun 8, 2026 10:59pm

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@halvaradop, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 51 minutes. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a547007c-ffd2-426c-a9d5-7ec4de394add

📥 Commits

Reviewing files that changed from the base of the PR and between 93f32e2 and f5e65b5.

📒 Files selected for processing (1)
  • packages/core/CHANGELOG.md
📝 Walkthrough

Walkthrough

This PR adds support for custom OAuth user info request callbacks, allowing OAuth provider configuration to define a userInfo.request function that receives structured token context and returns the user profile. The getUserInfo function is refactored to accept the full access token response object and dispatch between custom callback and default HTTP request paths.

Changes

Custom OAuth UserInfo Request Callback Feature

Layer / File(s) Summary
OAuth token context and userInfo configuration types
packages/core/src/@types/oauth.ts
Introduces AccessTokenContext type with token fields (access token, type, expiry, refresh token, scope, userinfo URL), extends OAuthProviderConfig.userInfo to support a request callback receiving that context, and exports CustomUserInfoFunction type.
UserInfo retrieval refactor with custom request support
packages/core/src/actions/callback/userinfo.ts
Refactors getUserInfo to accept the full access token response object, introduces createUserInfoRequest helper for standard OAuth userinfo HTTP requests (Bearer token, custom headers, error handling), and implements conditional dispatch between custom userInfo.request callbacks and the default helper.
Type guard, callback integration, and shared exports
packages/core/src/shared/assert.ts, packages/core/src/actions/callback/callback.ts, packages/core/src/shared/index.ts
Adds isCustomUserInfoFunction type guard, updates the callback flow to pass the full accessToken object to getUserInfo, imports OAuthProviderConfig in assertions, and re-exports fetchAsync.
Test updates and custom userInfo.request coverage
packages/core/test/actions/callback/userinfo.test.ts
Updates existing getUserInfo invocations to pass access token as an object with access_token field, adds typed Profile shape to custom profile test, and introduces two new test cases validating custom userInfo.request execution and error rejection.
Changelog documentation
packages/core/CHANGELOG.md
Documents the new custom userInfo function feature in the Unreleased section.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • aura-stack-ts/auth#109: Both PRs extend the OAuth userInfo provider configuration; this PR builds on earlier URL/headers object support by adding the userInfo.request callback path and typed token context.

Suggested labels

feature, refactor

Poem

🐰 A token arrived with tales to tell,
Custom requests answer the OAuth bell,
Context unpacked, no fetch to compile—
Let them retrieve as they please, with style! 🌙

🚥 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 pull request title accurately summarizes the main change: adding support for custom userInfo functions in OAuth providers, which is the core feature across all modified files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/add-custom-userinfo-function

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/core/src/actions/callback/userinfo.ts (1)

59-75: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Parse OAuth error payload before the non-2xx early throw.

Line 59 currently throws on !response.ok before Line 65 can parse OAuth error bodies, so standard provider error JSON on 4xx/5xx never gets normalized.

Proposed fix
-        if (!response.ok) {
-            logger?.log("OAUTH_USERINFO_INVALID_RESPONSE")
-            throw new OAuthProtocolError("INVALID_REQUEST", "Invalid userinfo response format")
-        }
-
         const json = await response.json()
         const { success, data } = OAuthErrorResponse.safeParse(json)
         if (success) {
             logger?.log("OAUTH_USERINFO_ERROR", {
                 message: "Error response received from OAuth userinfo endpoint",
@@
             })
             throw new OAuthProtocolError("INVALID_REQUEST", "An error was received from the OAuth userinfo endpoint.")
         }
+        if (!response.ok) {
+            logger?.log("OAUTH_USERINFO_INVALID_RESPONSE")
+            throw new OAuthProtocolError("INVALID_REQUEST", "Invalid userinfo response format")
+        }
         logger?.log("OAUTH_USERINFO_SUCCESS")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/actions/callback/userinfo.ts` around lines 59 - 75, When a
non-2xx response arrives, parse the response body and inspect it with
OAuthErrorResponse.safeParse before immediately throwing; specifically, in the
code around response handling in packages/core/src/actions/callback/userinfo.ts
use await response.json() and call OAuthErrorResponse.safeParse(json) when
!response.ok, and if the parse indicates an OAuth error, log via
logger?.log("OAUTH_USERINFO_ERROR", { message: ..., structuredData: { error,
error_description } }) and throw an OAuthProtocolError with that context; only
if the body is not a normalized OAuth error fall back to the current generic
logger?.log("OAUTH_USERINFO_INVALID_RESPONSE") and throw the generic
OAuthProtocolError. Ensure you reference response, OAuthErrorResponse.safeParse,
logger?.log, and OAuthProtocolError when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/CHANGELOG.md`:
- Line 13: Update the CHANGELOG sentence describing the OAuth provider
`userInfo` option to explicitly state the allowed shapes: it accepts either a
URL string, or an object with a `url` and optional `headers`/`method`, or an
object `{ url, request }`, or a custom `userInfo` function (which lets callers
perform the user info request themselves); replace the ambiguous phrase “URL
string or custom headers” with this precise contract to avoid implying
headers-only configuration is valid.

---

Outside diff comments:
In `@packages/core/src/actions/callback/userinfo.ts`:
- Around line 59-75: When a non-2xx response arrives, parse the response body
and inspect it with OAuthErrorResponse.safeParse before immediately throwing;
specifically, in the code around response handling in
packages/core/src/actions/callback/userinfo.ts use await response.json() and
call OAuthErrorResponse.safeParse(json) when !response.ok, and if the parse
indicates an OAuth error, log via logger?.log("OAUTH_USERINFO_ERROR", { message:
..., structuredData: { error, error_description } }) and throw an
OAuthProtocolError with that context; only if the body is not a normalized OAuth
error fall back to the current generic
logger?.log("OAUTH_USERINFO_INVALID_RESPONSE") and throw the generic
OAuthProtocolError. Ensure you reference response, OAuthErrorResponse.safeParse,
logger?.log, and OAuthProtocolError when making the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4289ae1f-5fda-4c0c-a886-451da7aa381a

📥 Commits

Reviewing files that changed from the base of the PR and between 31b5344 and 93f32e2.

📒 Files selected for processing (7)
  • packages/core/CHANGELOG.md
  • packages/core/src/@types/oauth.ts
  • packages/core/src/actions/callback/callback.ts
  • packages/core/src/actions/callback/userinfo.ts
  • packages/core/src/shared/assert.ts
  • packages/core/src/shared/index.ts
  • packages/core/test/actions/callback/userinfo.test.ts

Comment thread packages/core/CHANGELOG.md Outdated
@halvaradop halvaradop merged commit 33f0a3b into master Jun 8, 2026
5 of 6 checks passed
@halvaradop halvaradop deleted the feat/add-custom-userinfo-function branch June 8, 2026 22:59
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.

1 participant