From fe9600bc0734eeb2e6fbb0c53d3b81888bd4247d Mon Sep 17 00:00:00 2001 From: Gustavo Valverde Date: Sun, 7 Jun 2026 21:09:27 -0700 Subject: [PATCH] feat(oauth-provider): accept POST on the userinfo endpoint (#9937) --- .changeset/oauth-provider-userinfo-post.md | 5 +++++ packages/oauth-provider/src/oauth.ts | 2 +- packages/oauth-provider/src/userinfo.test.ts | 15 +++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 .changeset/oauth-provider-userinfo-post.md diff --git a/.changeset/oauth-provider-userinfo-post.md b/.changeset/oauth-provider-userinfo-post.md new file mode 100644 index 0000000000..81be7458b7 --- /dev/null +++ b/.changeset/oauth-provider-userinfo-post.md @@ -0,0 +1,5 @@ +--- +"@better-auth/oauth-provider": patch +--- + +The UserInfo endpoint (`/oauth2/userinfo`) now accepts `POST` with the access token in the `Authorization` header, in addition to `GET`. diff --git a/packages/oauth-provider/src/oauth.ts b/packages/oauth-provider/src/oauth.ts index 2ce838e7a7..24d6405879 100644 --- a/packages/oauth-provider/src/oauth.ts +++ b/packages/oauth-provider/src/oauth.ts @@ -1112,7 +1112,7 @@ export const oauthProvider = >(options: O) => { oauth2UserInfo: createAuthEndpoint( "/oauth2/userinfo", { - method: "GET", + method: ["GET", "POST"], metadata: { openapi: { description: diff --git a/packages/oauth-provider/src/userinfo.test.ts b/packages/oauth-provider/src/userinfo.test.ts index 1dce9def88..e64ce68531 100644 --- a/packages/oauth-provider/src/userinfo.test.ts +++ b/packages/oauth-provider/src/userinfo.test.ts @@ -198,6 +198,21 @@ describe("oauth userinfo", async () => { }); }); + it("should accept POST with the bearer token in the Authorization header", async () => { + const tokens = await getTokens(); + expect(tokens.data?.access_token).toBeDefined(); + const userinfo = await client.$fetch>( + "/oauth2/userinfo", + { + method: "POST", + headers: { + authorization: `Bearer ${tokens.data?.access_token ?? ""}`, + }, + }, + ); + expect(userinfo.data).toMatchObject({ sub: user.id }); + }); + /** * Programmatic callers have no `ctx.request`, so userinfo must resolve the * bearer token from `ctx.headers` for both transports.