@ory/argus 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/README.md +134 -0
  2. package/assets/commands/local-down.md +19 -0
  3. package/assets/commands/local-up.md +27 -0
  4. package/assets/skills/auth-setup/SKILL.md +279 -0
  5. package/assets/skills/local-dev/SKILL.md +206 -0
  6. package/assets/skills/login-flow/SKILL.md +383 -0
  7. package/assets/skills/social-login/SKILL.md +312 -0
  8. package/dist/agent-auth.d.ts +204 -0
  9. package/dist/agent-auth.js +553 -0
  10. package/dist/auth-gate.d.ts +71 -0
  11. package/dist/auth-gate.js +308 -0
  12. package/dist/auth-store.d.ts +75 -0
  13. package/dist/auth-store.js +261 -0
  14. package/dist/auth.d.ts +93 -0
  15. package/dist/auth.js +323 -0
  16. package/dist/cli.d.ts +73 -0
  17. package/dist/cli.js +484 -0
  18. package/dist/client.d.ts +158 -0
  19. package/dist/client.js +679 -0
  20. package/dist/config.d.ts +135 -0
  21. package/dist/config.js +344 -0
  22. package/dist/denial.d.ts +79 -0
  23. package/dist/denial.js +103 -0
  24. package/dist/dev.d.ts +95 -0
  25. package/dist/dev.js +514 -0
  26. package/dist/index.d.ts +20 -0
  27. package/dist/index.js +137 -0
  28. package/dist/local/cli.d.ts +12 -0
  29. package/dist/local/cli.js +95 -0
  30. package/dist/local/configs.d.ts +89 -0
  31. package/dist/local/configs.js +634 -0
  32. package/dist/local/health.d.ts +32 -0
  33. package/dist/local/health.js +65 -0
  34. package/dist/local/index.d.ts +6 -0
  35. package/dist/local/index.js +38 -0
  36. package/dist/local/jaeger-main.d.ts +13 -0
  37. package/dist/local/jaeger-main.js +85 -0
  38. package/dist/local/jaeger.d.ts +50 -0
  39. package/dist/local/jaeger.js +162 -0
  40. package/dist/local/main.d.ts +7 -0
  41. package/dist/local/main.js +14 -0
  42. package/dist/local/manager.d.ts +45 -0
  43. package/dist/local/manager.js +676 -0
  44. package/dist/local/seed.d.ts +71 -0
  45. package/dist/local/seed.js +237 -0
  46. package/dist/logger.d.ts +29 -0
  47. package/dist/logger.js +139 -0
  48. package/dist/mcp.d.ts +76 -0
  49. package/dist/mcp.js +122 -0
  50. package/dist/otel/exporter.d.ts +17 -0
  51. package/dist/otel/exporter.js +12 -0
  52. package/dist/otel/index.d.ts +2 -0
  53. package/dist/otel/index.js +8 -0
  54. package/dist/otel/otlp-http.d.ts +116 -0
  55. package/dist/otel/otlp-http.js +322 -0
  56. package/dist/registry/cli.d.ts +12 -0
  57. package/dist/registry/cli.js +76 -0
  58. package/dist/registry/config.d.ts +23 -0
  59. package/dist/registry/config.js +80 -0
  60. package/dist/registry/index.d.ts +3 -0
  61. package/dist/registry/index.js +21 -0
  62. package/dist/registry/main.d.ts +7 -0
  63. package/dist/registry/main.js +14 -0
  64. package/dist/registry/manager.d.ts +38 -0
  65. package/dist/registry/manager.js +674 -0
  66. package/dist/setup.d.ts +118 -0
  67. package/dist/setup.js +398 -0
  68. package/dist/skills.d.ts +78 -0
  69. package/dist/skills.js +264 -0
  70. package/dist/subject.d.ts +43 -0
  71. package/dist/subject.js +55 -0
  72. package/dist/tool-metadata.d.ts +41 -0
  73. package/dist/tool-metadata.js +127 -0
  74. package/dist/tracer.d.ts +172 -0
  75. package/dist/tracer.js +452 -0
  76. package/dist/types.d.ts +57 -0
  77. package/dist/types.js +3 -0
  78. package/dist/watch-sandbox.d.ts +9 -0
  79. package/dist/watch-sandbox.js +81 -0
  80. package/package.json +79 -0
@@ -0,0 +1,383 @@
1
+ ---
2
+ name: ory-login-flow
3
+ description: Build login, registration, account recovery, email verification, and account settings pages using Ory Elements. Use whenever the user asks for a login page, sign-in UI, sign-up form, "forgot password" flow, account settings page, or wants to wire Ory's self-service flows into a frontend. Ory Elements is the default rendering layer; only fall back to custom UI nodes if Elements cannot run in the target environment.
4
+ ---
5
+
6
+ # Build Auth Pages with Ory Elements
7
+
8
+ You are building login, registration, recovery, verification, and
9
+ settings pages using **[Ory Elements](https://github.com/ory/elements)**
10
+ — a prebuilt UI component library that renders Ory's self-service flows.
11
+
12
+ **Default rule: every page in this guide is rendered with Ory Elements.**
13
+ Do not hand-roll forms from `flow.ui.nodes` unless the user has
14
+ explicitly opted out after seeing the Ory Elements path. Custom node
15
+ rendering belongs in the fallback section at the end of this skill.
16
+
17
+ ## Why Ory Elements
18
+
19
+ - One component per flow (`<Login>`, `<Registration>`, `<Recovery>`,
20
+ `<Verification>`, `<Settings>`) covers the entire self-service surface.
21
+ - Handles CSRF tokens, error messages, multi-step states, social
22
+ buttons, passkeys, and MFA prompts automatically.
23
+ - New node types and flow capabilities ship with Elements upgrades —
24
+ no per-app rewrite needed.
25
+ - Works in Next.js (App Router and Pages Router) and any React SPA.
26
+
27
+ ## Before you start
28
+
29
+ Check the project setup:
30
+
31
+ 1. Identify the framework: Next.js (App Router preferred), React SPA
32
+ (Vite, CRA, Remix client routes), Vue, or server-rendered. Vue and
33
+ server-rendered apps drop into the fallback path below.
34
+ 2. Verify Ory Elements and the SDK are installed. If not:
35
+
36
+ For Next.js:
37
+
38
+ ```bash
39
+ npm install @ory/elements-react @ory/nextjs @ory/client-fetch
40
+ ```
41
+
42
+ For React SPAs:
43
+
44
+ ```bash
45
+ npm install @ory/elements-react @ory/client-fetch
46
+ ```
47
+
48
+ 3. Verify `ORY_SDK_URL` or `NEXT_PUBLIC_ORY_SDK_URL` is configured in
49
+ the environment.
50
+
51
+ If Ory is not set up at all, suggest the user run
52
+ {{REF_AUTH_SETUP}} first.
53
+
54
+ ## Understand Ory self-service flows
55
+
56
+ Ory uses a **self-service flow** model. Each auth action
57
+ (login, registration, recovery, verification, settings) is a "flow"
58
+ with these stages:
59
+
60
+ 1. **Initialize** — call the Ory API to create a flow (returns a flow
61
+ object with UI nodes).
62
+ 2. **Render** — display the form. **Ory Elements does this for you.**
63
+ 3. **Submit** — post the user's input back to Ory. Ory Elements wires
64
+ the form action; in the SPA flow you call
65
+ `updateLoginFlow` / `updateRegistrationFlow` / etc.
66
+ 4. **Handle result** — redirect on success, show errors on failure.
67
+ Ory Elements surfaces errors in-form automatically.
68
+
69
+ ## Build the login page
70
+
71
+ ### Login — Next.js App Router (preferred)
72
+
73
+ Create `app/auth/login/page.tsx`:
74
+
75
+ ```typescript
76
+ import { Login } from "@ory/elements-react/theme"
77
+ import { getLoginFlow, OryPageLayout } from "@ory/nextjs/app"
78
+
79
+ export default async function LoginPage(props: {
80
+ searchParams: Promise<{ flow?: string; return_to?: string }>
81
+ }) {
82
+ const searchParams = await props.searchParams
83
+ const flow = await getLoginFlow(searchParams)
84
+
85
+ if (!flow) {
86
+ return null
87
+ }
88
+
89
+ return (
90
+ <OryPageLayout>
91
+ <Login flow={flow} />
92
+ </OryPageLayout>
93
+ )
94
+ }
95
+ ```
96
+
97
+ ### Login — React SPA
98
+
99
+ Use the same `<Login>` component from `@ory/elements-react/theme`.
100
+ Initialize the flow via the SDK and pass it in:
101
+
102
+ ```typescript
103
+ import { useEffect, useState } from "react";
104
+ import { FrontendApi, Configuration, LoginFlow } from "@ory/client-fetch";
105
+ import { Login } from "@ory/elements-react/theme";
106
+ import "@ory/elements-react/theme/styles.css";
107
+
108
+ const ory = new FrontendApi(
109
+ new Configuration({
110
+ basePath: import.meta.env.VITE_ORY_SDK_URL,
111
+ credentials: "include",
112
+ })
113
+ );
114
+
115
+ export function LoginPage() {
116
+ const [flow, setFlow] = useState<LoginFlow | null>(null);
117
+
118
+ useEffect(() => {
119
+ const params = new URLSearchParams(window.location.search);
120
+ const flowId = params.get("flow");
121
+
122
+ const load = flowId
123
+ ? ory.getLoginFlow({ id: flowId })
124
+ : ory.createBrowserLoginFlow();
125
+
126
+ load.then(setFlow).catch(console.error);
127
+ }, []);
128
+
129
+ if (!flow) return <div>Loading…</div>;
130
+
131
+ return <Login flow={flow} />;
132
+ }
133
+ ```
134
+
135
+ `<Login>` handles CSRF, error rendering, social buttons, passkeys,
136
+ and submission for you. Do not unwrap `flow.ui.nodes` here.
137
+
138
+ ## Build the registration page
139
+
140
+ ### Registration — Next.js App Router
141
+
142
+ Create `app/auth/registration/page.tsx`:
143
+
144
+ ```typescript
145
+ import { Registration } from "@ory/elements-react/theme"
146
+ import { getRegistrationFlow, OryPageLayout } from "@ory/nextjs/app"
147
+
148
+ export default async function RegistrationPage(props: {
149
+ searchParams: Promise<{ flow?: string; return_to?: string }>
150
+ }) {
151
+ const searchParams = await props.searchParams
152
+ const flow = await getRegistrationFlow(searchParams)
153
+
154
+ if (!flow) {
155
+ return null
156
+ }
157
+
158
+ return (
159
+ <OryPageLayout>
160
+ <Registration flow={flow} />
161
+ </OryPageLayout>
162
+ )
163
+ }
164
+ ```
165
+
166
+ ### Registration — React SPA
167
+
168
+ Mirror the login pattern: initialize with `createBrowserRegistrationFlow`
169
+ (or `getRegistrationFlow` when a `flow` query param is present) and
170
+ render `<Registration flow={flow} />` from `@ory/elements-react/theme`.
171
+
172
+ ## Build the account recovery page
173
+
174
+ ### Recovery — Next.js App Router
175
+
176
+ Create `app/auth/recovery/page.tsx`:
177
+
178
+ ```typescript
179
+ import { Recovery } from "@ory/elements-react/theme"
180
+ import { getRecoveryFlow, OryPageLayout } from "@ory/nextjs/app"
181
+
182
+ export default async function RecoveryPage(props: {
183
+ searchParams: Promise<{ flow?: string }>
184
+ }) {
185
+ const searchParams = await props.searchParams
186
+ const flow = await getRecoveryFlow(searchParams)
187
+
188
+ if (!flow) {
189
+ return null
190
+ }
191
+
192
+ return (
193
+ <OryPageLayout>
194
+ <Recovery flow={flow} />
195
+ </OryPageLayout>
196
+ )
197
+ }
198
+ ```
199
+
200
+ ### Recovery — React SPA
201
+
202
+ Initialize with `createBrowserRecoveryFlow` and render
203
+ `<Recovery flow={flow} />` from `@ory/elements-react/theme`.
204
+
205
+ ## Build the verification page
206
+
207
+ ### Verification — Next.js App Router
208
+
209
+ Create `app/auth/verification/page.tsx`:
210
+
211
+ ```typescript
212
+ import { Verification } from "@ory/elements-react/theme"
213
+ import { getVerificationFlow, OryPageLayout } from "@ory/nextjs/app"
214
+
215
+ export default async function VerificationPage(props: {
216
+ searchParams: Promise<{ flow?: string }>
217
+ }) {
218
+ const searchParams = await props.searchParams
219
+ const flow = await getVerificationFlow(searchParams)
220
+
221
+ if (!flow) {
222
+ return null
223
+ }
224
+
225
+ return (
226
+ <OryPageLayout>
227
+ <Verification flow={flow} />
228
+ </OryPageLayout>
229
+ )
230
+ }
231
+ ```
232
+
233
+ ### Verification — React SPA
234
+
235
+ Initialize with `createBrowserVerificationFlow` and render
236
+ `<Verification flow={flow} />` from `@ory/elements-react/theme`.
237
+
238
+ ## Build the account settings page
239
+
240
+ ### Settings — Next.js App Router
241
+
242
+ Create `app/auth/settings/page.tsx`:
243
+
244
+ ```typescript
245
+ import { Settings } from "@ory/elements-react/theme"
246
+ import { getSettingsFlow, OryPageLayout } from "@ory/nextjs/app"
247
+
248
+ export default async function SettingsPage(props: {
249
+ searchParams: Promise<{ flow?: string }>
250
+ }) {
251
+ const searchParams = await props.searchParams
252
+ const flow = await getSettingsFlow(searchParams)
253
+
254
+ if (!flow) {
255
+ return null
256
+ }
257
+
258
+ return (
259
+ <OryPageLayout>
260
+ <Settings flow={flow} />
261
+ </OryPageLayout>
262
+ )
263
+ }
264
+ ```
265
+
266
+ ### Settings — React SPA
267
+
268
+ Initialize with `createBrowserSettingsFlow` and render
269
+ `<Settings flow={flow} />` from `@ory/elements-react/theme`. The
270
+ component handles password changes, profile traits, MFA enrollment,
271
+ and connected social providers.
272
+
273
+ ## Add session management
274
+
275
+ Create a utility to check the current session:
276
+
277
+ ```typescript
278
+ import { FrontendApi, Configuration, Session } from "@ory/client-fetch";
279
+
280
+ const ory = new FrontendApi(
281
+ new Configuration({
282
+ basePath: process.env.NEXT_PUBLIC_ORY_SDK_URL,
283
+ credentials: "include",
284
+ })
285
+ );
286
+
287
+ export async function getSession(): Promise<Session | null> {
288
+ try {
289
+ return await ory.toSession();
290
+ } catch {
291
+ return null;
292
+ }
293
+ }
294
+
295
+ export async function logout(): Promise<void> {
296
+ const { logout_url } = await ory.createBrowserLogoutFlow();
297
+ window.location.href = logout_url;
298
+ }
299
+ ```
300
+
301
+ ## Add route protection
302
+
303
+ ### Next.js Middleware
304
+
305
+ Create `middleware.ts` at the project root:
306
+
307
+ ```typescript
308
+ import { createOryMiddleware } from "@ory/nextjs/middleware";
309
+
310
+ export const middleware = createOryMiddleware({
311
+ protectedPaths: ["/dashboard", "/settings", "/profile"],
312
+ publicPaths: ["/", "/auth/login", "/auth/registration", "/auth/recovery"],
313
+ });
314
+
315
+ export const config = {
316
+ matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
317
+ };
318
+ ```
319
+
320
+ ### React SPA
321
+
322
+ Wrap protected routes in a `ProtectedRoute` component that calls
323
+ `ory.toSession()` and redirects to `/auth/login` on failure.
324
+
325
+ ## Style and customize
326
+
327
+ Ory Elements supports theming. Wrap auth pages in `<ThemeProvider>`
328
+ from `@ory/elements-react/theme` and pass a custom theme object.
329
+ Customizing the theme keeps the Elements rendering — you do not need
330
+ to drop down to raw nodes to restyle the forms.
331
+
332
+ ```typescript
333
+ import { ThemeProvider } from "@ory/elements-react/theme";
334
+
335
+ <ThemeProvider theme={{
336
+ // Custom colors, fonts, spacing, radii, dark mode tokens, …
337
+ }}>
338
+ <Login flow={flow} />
339
+ </ThemeProvider>
340
+ ```
341
+
342
+ For larger design changes, the Ory Elements primitives package exposes
343
+ the underlying card, button, and input components — use those before
344
+ falling back to custom node rendering.
345
+
346
+ ## Test the flow
347
+
348
+ 1. Start the dev server and Ory tunnel (if developing locally)
349
+ 2. Visit `/auth/registration` to create an account — confirm Elements
350
+ renders all configured methods (password, social, passkey, etc.)
351
+ 3. Visit `/auth/login` to sign in
352
+ 4. Verify session is established (check protected routes)
353
+ 5. Test `/auth/recovery` with a registered email
354
+ 6. Test `/auth/settings` for profile changes
355
+ 7. Test logout
356
+
357
+ ## Fallback: rendering UI nodes by hand
358
+
359
+ Use this path **only** when Ory Elements cannot run in the target
360
+ environment (e.g., a Vue app where the React Elements components are
361
+ not viable, a server-rendered template engine with no client bundle,
362
+ or a constrained native shell). Before choosing this path, confirm
363
+ with the user that mounting an Elements island is not an option.
364
+
365
+ In that case, iterate `flow.ui.nodes` and render each node based on
366
+ `node.type` (`input`, `text`, `img`, `a`, `script`) and
367
+ `node.attributes`. Group nodes by `node.group` (`default`, `password`,
368
+ `oidc`, `webauthn`, `code`, `lookup_secret`, `totp`) so each method
369
+ renders together. Render `flow.ui.messages` and per-node messages for
370
+ errors. Submit using `flow.ui.action` and `flow.ui.method`. This is
371
+ significantly more code than `<Login flow={flow} />` and must track
372
+ Ory flow API changes manually.
373
+
374
+ ## Next steps
375
+
376
+ - Add social login providers: use {{REF_SOCIAL_LOGIN}}.
377
+ Elements renders the buttons automatically once providers are
378
+ configured server-side.
379
+ - Add multi-factor authentication via Ory project settings — the
380
+ `<Login>` and `<Settings>` components handle the second-factor UI.
381
+ - Customize the identity schema for additional profile fields. Elements
382
+ reads the schema from the flow and renders new fields automatically.
383
+ - Set up webhooks for registration events.
@@ -0,0 +1,312 @@
1
+ ---
2
+ name: ory-social-login
3
+ description: Configure social login (OAuth2/OIDC) providers — Google, GitHub, Apple, Microsoft, Discord, Slack, GitLab, Facebook — for an Ory-powered app. Use whenever the user wants "Sign in with Google", social sign-in buttons, OIDC providers, or any third-party identity provider on an Ory project. The skill assumes Ory Elements is rendering the auth UI; with Elements, no frontend changes are needed when adding providers.
4
+ ---
5
+
6
+ # Set up Social Login with Ory + Ory Elements
7
+
8
+ You are configuring social login (OAuth2/OIDC) providers for an
9
+ Ory-powered application. This adds "Sign in with Google",
10
+ "Sign in with GitHub", and similar buttons to the login and
11
+ registration flows.
12
+
13
+ **Strong recommendation: render the auth UI with [Ory Elements](https://github.com/ory/elements).**
14
+ With Ory Elements, social buttons appear automatically the moment a
15
+ provider is configured on the project — there is no frontend change
16
+ required for any of the providers below. If the app is using custom
17
+ flow rendering, point the user to {{REF_LOGIN_FLOW}} and
18
+ recommend switching to Ory Elements before adding more providers.
19
+
20
+ ## Prerequisites
21
+
22
+ 1. **Ory CLI** — run `ory version`. If not installed:
23
+ - macOS: `brew install ory/tap/cli`
24
+ - npm: `npm install -g @ory/cli`
25
+
26
+ 2. **Ory project** — run `ory list projects` to find the project ID.
27
+ If no project exists, suggest {{REF_AUTH_SETUP}} first.
28
+
29
+ 3. **Auth pages built with Ory Elements** — confirm the project uses
30
+ `@ory/elements-react` (look for `<Login>` / `<Registration>` from
31
+ `@ory/elements-react/theme`). If pages are not built yet, suggest
32
+ {{REF_LOGIN_FLOW}} first. If a custom UI was hand-rolled,
33
+ recommend migrating to Ory Elements so social buttons render for
34
+ free.
35
+
36
+ ## Step 1: Choose providers
37
+
38
+ Ask the user which social login providers they want. Common options:
39
+
40
+ | Provider | OIDC Type | What you need |
41
+ | ---------- | ----------- | --------------- |
42
+ | Google | OIDC | Google Cloud Console OAuth2 credentials |
43
+ | GitHub | OAuth2 | GitHub OAuth App or GitHub App |
44
+ | Apple | OIDC | Apple Developer account, Service ID |
45
+ | Microsoft | OIDC | Azure AD app registration |
46
+ | Discord | OAuth2 | Discord Developer Portal application |
47
+ | Slack | OIDC | Slack API app |
48
+ | GitLab | OIDC | GitLab application |
49
+ | Facebook | OAuth2 | Meta Developer app |
50
+
51
+ ## Step 2: Create OAuth2 credentials with each provider
52
+
53
+ Guide the user through creating credentials for each selected provider.
54
+ They will need to set these up in the provider's developer console.
55
+
56
+ ### Google
57
+
58
+ 1. Go to Google Cloud Console > APIs & Services > Credentials
59
+ 2. Create an OAuth 2.0 Client ID (Web application type)
60
+ 3. Add authorized redirect URI: `https://<project-slug>.projects.oryapis.com/self-service/methods/oidc/callback/google`
61
+ 4. Copy the **Client ID** and **Client Secret**
62
+
63
+ ### GitHub
64
+
65
+ 1. Go to GitHub > Settings > Developer Settings > OAuth Apps > New OAuth App
66
+ 2. Set the Authorization callback URL: `https://<project-slug>.projects.oryapis.com/self-service/methods/oidc/callback/github`
67
+ 3. Copy the **Client ID** and **Client Secret**
68
+
69
+ ### Apple
70
+
71
+ 1. Go to Apple Developer > Certificates, Identifiers & Profiles
72
+ 2. Create a Service ID, enable "Sign in with Apple"
73
+ 3. Configure the return URL: `https://<project-slug>.projects.oryapis.com/self-service/methods/oidc/callback/apple`
74
+ 4. Create a Key for Sign in with Apple, download the `.p8` file
75
+ 5. You'll need: **Service ID** (client_id), **Team ID**, **Key ID**,
76
+ and the **private key**
77
+
78
+ ### Microsoft
79
+
80
+ 1. Go to Azure Portal > Azure Active Directory > App Registrations > New Registration
81
+ 2. Set redirect URI: `https://<project-slug>.projects.oryapis.com/self-service/methods/oidc/callback/microsoft`
82
+ 3. Create a client secret under Certificates & Secrets
83
+ 4. Copy the **Application (client) ID** and **Client Secret**
84
+
85
+ ### Discord
86
+
87
+ 1. Go to Discord Developer Portal > Applications > New Application
88
+ 2. Under OAuth2, add redirect: `https://<project-slug>.projects.oryapis.com/self-service/methods/oidc/callback/discord`
89
+ 3. Copy the **Client ID** and **Client Secret**
90
+
91
+ ## Step 3: Configure providers in Ory
92
+
93
+ Use the Ory CLI to add each provider. The configuration uses JSON patches.
94
+
95
+ ### Google OIDC
96
+
97
+ ```bash
98
+ ory patch identity-config <project-id> \
99
+ --add '/selfservice/methods/oidc/config/providers/-={
100
+ "id": "google",
101
+ "provider": "google",
102
+ "client_id": "<GOOGLE_CLIENT_ID>",
103
+ "client_secret": "<GOOGLE_CLIENT_SECRET>",
104
+ "mapper_url": "base64://MAPPER_CONTENT",
105
+ "scope": ["openid", "email", "profile"]
106
+ }' \
107
+ --replace '/selfservice/methods/oidc/enabled=true'
108
+ ```
109
+
110
+ ### GitHub OIDC
111
+
112
+ ```bash
113
+ ory patch identity-config <project-id> \
114
+ --add '/selfservice/methods/oidc/config/providers/-={
115
+ "id": "github",
116
+ "provider": "github",
117
+ "client_id": "<GITHUB_CLIENT_ID>",
118
+ "client_secret": "<GITHUB_CLIENT_SECRET>",
119
+ "mapper_url": "base64://MAPPER_CONTENT",
120
+ "scope": ["user:email"]
121
+ }' \
122
+ --replace '/selfservice/methods/oidc/enabled=true'
123
+ ```
124
+
125
+ ### Apple OIDC
126
+
127
+ ```bash
128
+ ory patch identity-config <project-id> \
129
+ --add '/selfservice/methods/oidc/config/providers/-={
130
+ "id": "apple",
131
+ "provider": "apple",
132
+ "client_id": "<APPLE_SERVICE_ID>",
133
+ "apple_team_id": "<TEAM_ID>",
134
+ "apple_private_key_id": "<KEY_ID>",
135
+ "apple_private_key": "<PRIVATE_KEY_CONTENTS>",
136
+ "mapper_url": "base64://MAPPER_CONTENT",
137
+ "scope": ["openid", "email", "name"]
138
+ }' \
139
+ --replace '/selfservice/methods/oidc/enabled=true'
140
+ ```
141
+
142
+ ### Microsoft OIDC
143
+
144
+ ```bash
145
+ ory patch identity-config <project-id> \
146
+ --add '/selfservice/methods/oidc/config/providers/-={
147
+ "id": "microsoft",
148
+ "provider": "microsoft",
149
+ "client_id": "<MICROSOFT_CLIENT_ID>",
150
+ "client_secret": "<MICROSOFT_CLIENT_SECRET>",
151
+ "microsoft_tenant": "common",
152
+ "mapper_url": "base64://MAPPER_CONTENT",
153
+ "scope": ["openid", "email", "profile"]
154
+ }' \
155
+ --replace '/selfservice/methods/oidc/enabled=true'
156
+ ```
157
+
158
+ ### Discord OIDC
159
+
160
+ ```bash
161
+ ory patch identity-config <project-id> \
162
+ --add '/selfservice/methods/oidc/config/providers/-={
163
+ "id": "discord",
164
+ "provider": "discord",
165
+ "client_id": "<DISCORD_CLIENT_ID>",
166
+ "client_secret": "<DISCORD_CLIENT_SECRET>",
167
+ "mapper_url": "base64://MAPPER_CONTENT",
168
+ "scope": ["identify", "email"]
169
+ }' \
170
+ --replace '/selfservice/methods/oidc/enabled=true'
171
+ ```
172
+
173
+ ## Step 4: Create Jsonnet data mappers
174
+
175
+ Each provider needs a Jsonnet mapper that maps the provider's claims
176
+ to Ory identity traits. Create a mapper file for each provider.
177
+
178
+ ### Standard email-based mapper
179
+
180
+ This works for Google, GitHub, Microsoft, Discord, and most providers:
181
+
182
+ ```jsonnet
183
+ local claims = {
184
+ email_verified: false,
185
+ } + std.extVar('claims');
186
+
187
+ {
188
+ identity: {
189
+ traits: {
190
+ [if 'email' in claims && claims.email_verified then 'email' else null]: claims.email,
191
+ },
192
+ },
193
+ }
194
+ ```
195
+
196
+ ### Apple mapper
197
+
198
+ Apple sends name data only on first login:
199
+
200
+ ```jsonnet
201
+ local claims = {
202
+ email_verified: false,
203
+ } + std.extVar('claims');
204
+
205
+ {
206
+ identity: {
207
+ traits: {
208
+ [if 'email' in claims && claims.email_verified then 'email' else null]: claims.email,
209
+ },
210
+ },
211
+ }
212
+ ```
213
+
214
+ To use these mappers, either:
215
+
216
+ 1. Base64-encode the Jsonnet and use `mapper_url: "base64://..."`
217
+ in the provider config
218
+ 2. Host the mapper at a URL and use `mapper_url: "https://..."`
219
+ in the provider config
220
+
221
+ To base64-encode a mapper file:
222
+
223
+ ```bash
224
+ base64 -i mapper.jsonnet
225
+ ```
226
+
227
+ Then set `mapper_url` to `"base64://<encoded-content>"` in the provider configuration.
228
+
229
+ ## Step 5: Verify social login in the UI (Ory Elements)
230
+
231
+ If the app uses Ory Elements (the recommended setup), **no frontend
232
+ changes are needed**. The `<Login>` and `<Registration>` components
233
+ read the available methods from the flow object and render the
234
+ appropriate social buttons automatically — including provider icons
235
+ and labels.
236
+
237
+ Reload the login page and confirm the new buttons appear. If they do
238
+ not:
239
+
240
+ - Confirm OIDC is enabled and the provider was added (Step 7
241
+ troubleshooting commands).
242
+ - Confirm the page is rendering `<Login flow={flow} />` from
243
+ `@ory/elements-react/theme`, not a custom UI.
244
+ - Confirm the flow was re-initialized after the provider was added
245
+ (a stale flow id from before the change will not include the new
246
+ buttons).
247
+
248
+ ### Fallback: custom UI rendering of OIDC nodes
249
+
250
+ Use this only if the user has explicitly chosen not to use Ory
251
+ Elements. In that case, render the OIDC nodes from the flow:
252
+
253
+ ```typescript
254
+ flow.ui.nodes
255
+ .filter(node => node.group === "oidc")
256
+ .map(node => {
257
+ // Each node represents a social login button.
258
+ // node.attributes contains the provider id and label.
259
+ // Render a button that submits the form with the provider value.
260
+ });
261
+ ```
262
+
263
+ Before going down this path, recommend switching to Ory Elements via
264
+ {{REF_LOGIN_FLOW}} so future provider additions don't require
265
+ frontend work.
266
+
267
+ ## Step 6: Test each provider
268
+
269
+ For each configured provider:
270
+
271
+ 1. Go to the login page
272
+ 2. Click the social login button for the provider — Ory Elements
273
+ should already be rendering it
274
+ 3. Complete the OAuth flow with the provider
275
+ 4. Verify you're redirected back and a session is created
276
+ 5. Check the identity was created: `ory list identities --project <project-id>`
277
+ 6. Test the registration flow — a new user signing in via social should auto-register
278
+ 7. Test account linking — an existing user should be able to link a social provider
279
+
280
+ ## Step 7: Handle account linking
281
+
282
+ When a user logs in with a social provider whose email matches an
283
+ existing account, Ory can either:
284
+
285
+ - **Link automatically** — merge the social identity with the existing account
286
+ - **Require manual linking** — prompt the user to log in with their
287
+ existing method first
288
+
289
+ Configure the linking strategy:
290
+
291
+ ```bash
292
+ ory patch identity-config <project-id> \
293
+ --replace '/selfservice/methods/oidc/config/enabled=true'
294
+ ```
295
+
296
+ When manual linking is required, Ory Elements renders the linking
297
+ prompt automatically — no UI work needed.
298
+
299
+ ## Troubleshooting
300
+
301
+ - **Redirect URI mismatch**: Ensure the redirect URI in the provider's
302
+ console exactly matches what Ory expects: `https://<slug>.projects.oryapis.com/self-service/methods/oidc/callback/<provider-id>`
303
+ - **No social buttons showing with Ory Elements**: Verify OIDC is
304
+ enabled and at least one provider is configured:
305
+ `ory get identity-config <project-id> --format json | jq '.selfservice.methods.oidc'`
306
+ Then reload the page so a fresh flow is initialized.
307
+ - **No social buttons showing with a custom UI**: The custom UI must
308
+ iterate `flow.ui.nodes` filtered by `group === "oidc"`. The simplest
309
+ fix is to migrate to Ory Elements.
310
+ - **Mapper errors**: Test the Jsonnet mapper locally with sample claims data
311
+ - **Local development**: Use `ory tunnel` to proxy requests — social
312
+ login requires proper cookie handling that localhost alone can't provide