feat: OAuth 2.0 support for atoms (#27158)

* fix: useOAuthClient support OAuth 2.0

* fix: cannot read properties of undefined (reading NEXT_PUBLIC_IS_E2E)

* fix: allow OAuth 2.0 token to connect gcal or ms calendar

* fix: allow OAuth 2.0 token to save gcal or ms calendar credentials

* refactor: dont set oauth id header for OAuth 2.0

* fix: calendar events not showing and emails not sent

* feat: CalOAuth2Provider

* chore: make OAuth 2.0 work in examples app

* chore: refresh OAuth 2.0 tokens

* docs: running examples app with oauth 2.0

* fix: remove sensitive console.log statements that leak secrets

Remove logging of:
- OAuth authorization codes (oauth2-user.ts)
- Token-bearing exchange responses (oauth2-user.ts)
- /me response data containing PII (oauth2-user.ts)
- OAuth2 refresh response with tokens (refresh.ts)
- Response payload with access tokens (_app.tsx)

Addresses Cubic AI review feedback for issues with confidence >= 9/10

Co-Authored-By: unknown <>

* docs: update readme

* fix: implemente cubic feedback

* fix: seed script import

* fix: seed script pkce

* fix: correct typos and SQLite capitalization in OAuth2 README (#27176)

Co-authored-by: cubic-dev-ai[bot] <1082092+cubic-dev-ai[bot]@users.noreply.github.com>

* refactor: dont return name in public oauth endpoint

* docs: CalOAuthProvider

* chore: add NEXT_PUBLIC_IS_E2E constant to test

* docs: fix duplicated 'or' in Cal OAuth Provider documentation (#27177)

Co-authored-by: cubic-dev-ai[bot] <1082092+cubic-dev-ai[bot]@users.noreply.github.com>

* revert: is e2e constant

* fix: typecheck

* refactor: example app users select

* update readme

* chore: update oauth atoms readme

* refactor: enable booking managed event types with user.username instead of profile.username

* fix: EventTypeSettings when viewing round robin

* test: add e2e tests for atoms-oauth2 controller

Co-Authored-By: lauris@cal.com <lauris.skraucis@gmail.com>

* fix: correct error message path in atoms-oauth2 e2e test

Co-Authored-By: lauris@cal.com <lauris.skraucis@gmail.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: cubic-dev-ai[bot] <1082092+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Rajiv Sahal <sahalrajiv-extc@atharvacoe.ac.in>
This commit is contained in:
Lauris Skraucis
2026-02-04 12:54:15 +01:00
committed by GitHub
co-authored by unknown <> cubic-dev-ai[bot] <1082092+cubic-dev-ai[bot]@users.noreply.github.com> cubic-dev-ai[bot] <1082092+cubic-dev-ai[bot]@users.noreply.github.com> lauris@cal.com <lauris.skraucis@gmail.com> lauris@cal.com <lauris.skraucis@gmail.com> Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> cubic-dev-ai[bot] <1082092+cubic-dev-ai[bot]@users.noreply.github.com> Rajiv Sahal
parent 0776bdf5fe
commit fc602d3b03
27 changed files with 663 additions and 65 deletions
@@ -0,0 +1,47 @@
---
title: "Cal OAuth Provider"
---
Cal OAuth Provider is used to setup Cal Atoms within your app after your users have authenticated using your Cal OAuth 2.0 client.
Your users will have authenticated with your Cal OAuth client and you will have access to their access tokens, which
the Cal Atoms will use to manage their event type settings, availability, etc. within your app.
It is used in the root of your app, be it _app.js or _app.tsx in case of
Next.js or App.js or App.ts in case of React. Here is an example:
```js
import "@calcom/atoms/globals.min.css";
import { CalOAuthProvider } from '@calcom/atoms';
function MyApp({ Component, pageProps }) {
const accessToken = "user-oauth-access-token";
return (
<CalOAuthProvider
accessToken={accessToken}
clientId={process.env.CAL_OAUTH2_CLIENT_ID ?? ""}
options={{
apiUrl: process.env.CAL_API_URL ?? "https://api.cal.com/v2",
refreshUrl: process.env.REFRESH_URL
}}
>
<Component {...pageProps} />
</CalOAuthProvider>
);
}
export default MyApp;
```
Below is a list of props that can be passed to the Cal OAuth Provider.
| Name | Required | Description |
|:----------------------------|:----------|:-------------------------------------------------------------------------------------------------------|
| clientId | Yes | Your OAuth2 client ID |
| options | Yes | Configuration options - `apiUrl` (should be https://api.cal.com/v2) and `refreshUrl` (URL of endpoint you have to build that to which atoms will send expired access tokens and receive new one in return. Read how to set it up [here](https://cal.com/docs/platform/quickstart#4-backend%3A-setting-up-a-refresh-token-endpoint)) and `readingDirection` (defaults to "ltr" but can also pass "rtl" which will change direction of UI components) |
| accessToken | Yes | The access token of your user for whom cal handles scheduling. |
| autoUpdateTimezone | No | Whether to automatically update managed user timezone (default: true) |
| language | No | Language code (default: "en") - available languages: "en", "de", "fr", "it", "nl", "pt-BR", "es" |
| organizationId | No | ID of your organization |