@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.
- package/README.md +134 -0
- package/assets/commands/local-down.md +19 -0
- package/assets/commands/local-up.md +27 -0
- package/assets/skills/auth-setup/SKILL.md +279 -0
- package/assets/skills/local-dev/SKILL.md +206 -0
- package/assets/skills/login-flow/SKILL.md +383 -0
- package/assets/skills/social-login/SKILL.md +312 -0
- package/dist/agent-auth.d.ts +204 -0
- package/dist/agent-auth.js +553 -0
- package/dist/auth-gate.d.ts +71 -0
- package/dist/auth-gate.js +308 -0
- package/dist/auth-store.d.ts +75 -0
- package/dist/auth-store.js +261 -0
- package/dist/auth.d.ts +93 -0
- package/dist/auth.js +323 -0
- package/dist/cli.d.ts +73 -0
- package/dist/cli.js +484 -0
- package/dist/client.d.ts +158 -0
- package/dist/client.js +679 -0
- package/dist/config.d.ts +135 -0
- package/dist/config.js +344 -0
- package/dist/denial.d.ts +79 -0
- package/dist/denial.js +103 -0
- package/dist/dev.d.ts +95 -0
- package/dist/dev.js +514 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +137 -0
- package/dist/local/cli.d.ts +12 -0
- package/dist/local/cli.js +95 -0
- package/dist/local/configs.d.ts +89 -0
- package/dist/local/configs.js +634 -0
- package/dist/local/health.d.ts +32 -0
- package/dist/local/health.js +65 -0
- package/dist/local/index.d.ts +6 -0
- package/dist/local/index.js +38 -0
- package/dist/local/jaeger-main.d.ts +13 -0
- package/dist/local/jaeger-main.js +85 -0
- package/dist/local/jaeger.d.ts +50 -0
- package/dist/local/jaeger.js +162 -0
- package/dist/local/main.d.ts +7 -0
- package/dist/local/main.js +14 -0
- package/dist/local/manager.d.ts +45 -0
- package/dist/local/manager.js +676 -0
- package/dist/local/seed.d.ts +71 -0
- package/dist/local/seed.js +237 -0
- package/dist/logger.d.ts +29 -0
- package/dist/logger.js +139 -0
- package/dist/mcp.d.ts +76 -0
- package/dist/mcp.js +122 -0
- package/dist/otel/exporter.d.ts +17 -0
- package/dist/otel/exporter.js +12 -0
- package/dist/otel/index.d.ts +2 -0
- package/dist/otel/index.js +8 -0
- package/dist/otel/otlp-http.d.ts +116 -0
- package/dist/otel/otlp-http.js +322 -0
- package/dist/registry/cli.d.ts +12 -0
- package/dist/registry/cli.js +76 -0
- package/dist/registry/config.d.ts +23 -0
- package/dist/registry/config.js +80 -0
- package/dist/registry/index.d.ts +3 -0
- package/dist/registry/index.js +21 -0
- package/dist/registry/main.d.ts +7 -0
- package/dist/registry/main.js +14 -0
- package/dist/registry/manager.d.ts +38 -0
- package/dist/registry/manager.js +674 -0
- package/dist/setup.d.ts +118 -0
- package/dist/setup.js +398 -0
- package/dist/skills.d.ts +78 -0
- package/dist/skills.js +264 -0
- package/dist/subject.d.ts +43 -0
- package/dist/subject.js +55 -0
- package/dist/tool-metadata.d.ts +41 -0
- package/dist/tool-metadata.js +127 -0
- package/dist/tracer.d.ts +172 -0
- package/dist/tracer.js +452 -0
- package/dist/types.d.ts +57 -0
- package/dist/types.js +3 -0
- package/dist/watch-sandbox.d.ts +9 -0
- package/dist/watch-sandbox.js +81 -0
- package/package.json +79 -0
package/README.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Ory Argus: Agent and Developer Experience
|
|
2
|
+
|
|
3
|
+
The core API behind every Ory Agent Plugin and Extension. Argus wraps [Ory Identities](https://www.ory.com/ory-ecosystem), [Ory Permissions](https://ory.com/permissions), MCP authorization, and distributed tracing into a single client. Each of the harness packages (`@ory/claude-code`, `@ory/codex`, `@ory/gemini-cli`, `@ory/openclaw`, `@ory/opencode`) is a thin adapter that maps one harness's hook contract onto Argus.
|
|
4
|
+
|
|
5
|
+
Argus is also published on its own so you can build new harness plugins or extensions, embed Ory into a custom agent runtime, or instrument any SDK that exposes event lifecycle hooks for session start, tool execution, and tool completion.
|
|
6
|
+
|
|
7
|
+
## Use
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { OryAgentClient } from "@ory/argus";
|
|
11
|
+
|
|
12
|
+
const client = OryAgentClient.fromEnv("my-harness");
|
|
13
|
+
|
|
14
|
+
const session = await client.verifySession(sessionToken);
|
|
15
|
+
|
|
16
|
+
const result = await client.checkPermission({
|
|
17
|
+
namespace: "AgentTools",
|
|
18
|
+
object: "Bash",
|
|
19
|
+
relation: "invoke",
|
|
20
|
+
subjectId: `session:${sessionId}`,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
if (!result.allowed) {
|
|
24
|
+
// block the tool call (or fail-open on result.error)
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`fromEnv()` returns a working client even when `ORY_PROJECT_URL` is unset; calls fail with `network_error` and the fail-open path handles them.
|
|
29
|
+
|
|
30
|
+
## Build a new plugin, extension, or custom integration
|
|
31
|
+
|
|
32
|
+
Any agent runtime, framework, or SDK that exposes lifecycle hooks for **session start**, **tool execution**, and **tool completion** can use Argus as its authentication, authorization, and audit layer. The integration contract is the same three calls every plugin in this repo makes:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import {
|
|
36
|
+
OryAgentClient,
|
|
37
|
+
ensureUserAuthenticated,
|
|
38
|
+
ensureAgentIdentity,
|
|
39
|
+
} from "@ory/argus";
|
|
40
|
+
|
|
41
|
+
const client = OryAgentClient.fromEnv("my-harness");
|
|
42
|
+
|
|
43
|
+
// 1. Session start: authenticate the human and the agent process.
|
|
44
|
+
async function onSessionStart() {
|
|
45
|
+
await ensureUserAuthenticated(client, {
|
|
46
|
+
binName: "my-harness",
|
|
47
|
+
harness: "my-harness",
|
|
48
|
+
allowBlock: true,
|
|
49
|
+
});
|
|
50
|
+
await ensureAgentIdentity(client, {
|
|
51
|
+
projectUrl: process.env.ORY_PROJECT_URL,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// 2. Before each tool call: check Ory Permissions; block on `deny`.
|
|
56
|
+
async function onBeforeTool(toolName: string, sessionId: string) {
|
|
57
|
+
const result = await client.checkPermission({
|
|
58
|
+
namespace: "AgentTools",
|
|
59
|
+
object: toolName,
|
|
60
|
+
relation: "invoke",
|
|
61
|
+
subjectId: `session:${sessionId}`,
|
|
62
|
+
});
|
|
63
|
+
if (result.allowed === false) {
|
|
64
|
+
return { block: true, reason: result.reason };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 3. After each tool call: record a structured trace span.
|
|
69
|
+
async function onAfterTool(toolName: string, durationMs: number) {
|
|
70
|
+
client.tracer.record("tool.complete", { toolName, durationMs });
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Map the host SDK's or harness's hook names onto those three calls and you get the same identity, policy, and audit story as every published plugin in this repo. Subprocess hosts can additionally block via exit codes; in-process hosts can return decision objects directly.
|
|
75
|
+
|
|
76
|
+
## Surface
|
|
77
|
+
|
|
78
|
+
### `OryAgentClient`
|
|
79
|
+
|
|
80
|
+
The wrapped Ory client. One instance per harness session.
|
|
81
|
+
|
|
82
|
+
| Group | Members |
|
|
83
|
+
|---|---|
|
|
84
|
+
| Sessions and tokens | `verifySession`, `introspectToken`, `classifyError` |
|
|
85
|
+
| Permission checks | `checkPermission`, `batchCheckPermissions`, `checkMcpPermission` |
|
|
86
|
+
| Principals (who is acting) | `setUserPrincipal`, `setAgentPrincipal` |
|
|
87
|
+
| Delegation tuples | `createRelationship`, `deleteRelationship` |
|
|
88
|
+
| Tracing | `tracer` (see Tracer below) |
|
|
89
|
+
|
|
90
|
+
### Identity gates
|
|
91
|
+
|
|
92
|
+
Resolve the user and agent identities at session start. Non-blocking by default; opt in to hard blocking on the user gate where the host can carry an exit-style decision.
|
|
93
|
+
|
|
94
|
+
| Helper | Purpose |
|
|
95
|
+
|---|---|
|
|
96
|
+
| `ensureUserAuthenticated` | Interactive PKCE login, token refresh, or env-token short-circuit |
|
|
97
|
+
| `ensureAgentIdentity` | OAuth2 dynamic client registration with persisted credentials |
|
|
98
|
+
| `ensureSubAgentIdentity` | Per-sub-agent identity for harnesses that fan out |
|
|
99
|
+
| `resolveUserSubject`, `subjectLabel` | Subject resolution and printable labels for spans and denial messages |
|
|
100
|
+
|
|
101
|
+
### Tracer
|
|
102
|
+
|
|
103
|
+
`Tracer` is exposed as `client.tracer`. Records every decision as a structured span.
|
|
104
|
+
|
|
105
|
+
- `record(event, attrs)`: emit a span
|
|
106
|
+
- `EventEmitter` `"span"` events for live observers
|
|
107
|
+
- NDJSON file output
|
|
108
|
+
- OTLP / HTTP export
|
|
109
|
+
|
|
110
|
+
### Logger
|
|
111
|
+
|
|
112
|
+
- `DebugLogger`: structured JSON to stderr plus optional log file
|
|
113
|
+
- Gated by `ORY_AGENT_DEBUG`
|
|
114
|
+
|
|
115
|
+
### Skill and command catalog
|
|
116
|
+
|
|
117
|
+
Materialize the canonical `SKILL.md` templates into each harness's native skill or command format.
|
|
118
|
+
|
|
119
|
+
| Helper | Purpose |
|
|
120
|
+
|---|---|
|
|
121
|
+
| `renderOrySkills`, `renderOryCommands` | Substitute template tokens (binary name, package name, reference style) |
|
|
122
|
+
| `commandToSkill`, `commandToToml`, `commandToFrontmatterMarkdown`, `commandToPlainMarkdown` | Format per harness |
|
|
123
|
+
| `writeSkillTree`, `removeSkillDirs` | Materialize on install, clean up on uninstall |
|
|
124
|
+
|
|
125
|
+
### CLI and dev tooling
|
|
126
|
+
|
|
127
|
+
- Shared CLI handlers used by every plugin's CLI: `configure`, `status`, `local`, `setup`
|
|
128
|
+
- `runDevLauncher(...)`: the dev-launcher pipeline used by every plugin
|
|
129
|
+
- Local-stack manager: brings up a local Ory instance in Docker Compose
|
|
130
|
+
- Verdaccio registry manager: a local npm registry for dev launchers
|
|
131
|
+
|
|
132
|
+
## License
|
|
133
|
+
|
|
134
|
+
Apache-2.0
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Stop Local Ory Environment
|
|
2
|
+
|
|
3
|
+
Stop the local Ory development environment. This gracefully shuts down
|
|
4
|
+
all Docker containers (Kratos, Keto, Hydra, Nginx gateway) while
|
|
5
|
+
preserving data volumes so you can restart later without losing state.
|
|
6
|
+
|
|
7
|
+
Run:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx {{BIN}} local down
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
To restart later, use {{REF_LOCAL_UP}}.
|
|
14
|
+
|
|
15
|
+
To stop **and** remove all data (full reset), run:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx {{BIN}} local reset
|
|
19
|
+
```
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Start Local Ory Environment
|
|
2
|
+
|
|
3
|
+
Start the local Ory development environment using Docker Compose.
|
|
4
|
+
This spins up Kratos (identity), Keto (permissions), Hydra (OAuth2),
|
|
5
|
+
and an Nginx gateway on port 4000.
|
|
6
|
+
|
|
7
|
+
Run:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx {{BIN}} local up
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
This will:
|
|
14
|
+
|
|
15
|
+
1. Start all Ory services in Docker containers
|
|
16
|
+
2. Wait for the gateway to become healthy
|
|
17
|
+
3. Seed test data (identity, session, and permission tuples)
|
|
18
|
+
4. Print environment variables to connect
|
|
19
|
+
|
|
20
|
+
After it completes, set the printed environment variables in your shell:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
eval "$(npx {{BIN}} local env)"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
If services are already running, stop them first with {{REF_LOCAL_DOWN}}
|
|
27
|
+
or use `npx {{BIN}} local status` to check the current state.
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ory-auth-setup
|
|
3
|
+
description: Set up a complete authentication system using Ory Network with Ory Elements as the UI layer. Use whenever the user wants to add login, registration, account recovery, email verification, account settings, or session management to a web app — even if they only mention "auth", "sign-in", or "users". Ory Elements is the default UI; only fall back to custom rendering when Ory Elements cannot be used.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Set up Ory Authentication with Ory Elements
|
|
7
|
+
|
|
8
|
+
You are setting up a complete authentication system using **Ory Network**
|
|
9
|
+
and **[Ory Elements](https://github.com/ory/elements)**. Ory Elements is
|
|
10
|
+
the default and strongly preferred UI layer for every flow (login,
|
|
11
|
+
registration, recovery, verification, settings). Build the system with
|
|
12
|
+
Ory Elements unless the user has an explicit, hard constraint that rules
|
|
13
|
+
it out — and even then, propose Ory Elements first and confirm before
|
|
14
|
+
choosing a different path.
|
|
15
|
+
|
|
16
|
+
## Why Ory Elements is the default
|
|
17
|
+
|
|
18
|
+
- **Covers every self-service flow out of the box** — login, registration,
|
|
19
|
+
recovery, verification, settings, MFA — with a single component per flow.
|
|
20
|
+
- **Renders the flow's UI nodes for you.** You do not need to map
|
|
21
|
+
`flow.ui.nodes` to form fields, handle CSRF tokens, error messages,
|
|
22
|
+
multi-step states, or method-specific logic by hand.
|
|
23
|
+
- **Social login and passkeys appear automatically** as soon as they are
|
|
24
|
+
enabled in the Ory project. No frontend changes needed.
|
|
25
|
+
- **Stays in sync with Ory's flow API** — when Ory adds a node type or
|
|
26
|
+
changes a contract, Ory Elements absorbs the change so your app does
|
|
27
|
+
not break.
|
|
28
|
+
- **Themeable and accessible** — the look-and-feel can be customized via
|
|
29
|
+
the theme provider without rebuilding flow logic.
|
|
30
|
+
|
|
31
|
+
If you find yourself writing `flow.ui.nodes.map(...)` to render auth UI,
|
|
32
|
+
stop and switch to Ory Elements. Custom node rendering is a fallback,
|
|
33
|
+
not a parallel option.
|
|
34
|
+
|
|
35
|
+
## Step 1: Check prerequisites
|
|
36
|
+
|
|
37
|
+
Before installing the Ory CLI, decide where the auth backend will run:
|
|
38
|
+
|
|
39
|
+
- **Ory Network** (default for production-bound work) — continue with
|
|
40
|
+
the steps below.
|
|
41
|
+
- **Local Ory stack** (no Network project required, ideal for
|
|
42
|
+
prototyping, offline work, or automated tests) — switch to the
|
|
43
|
+
{{REF_LOCAL_DEV}} skill. It manages a Dockerized
|
|
44
|
+
Kratos/Keto/Hydra stack via {{REF_LOCAL_UP}} and {{REF_LOCAL_DOWN}},
|
|
45
|
+
and the rest of this skill applies once the SDK URL points at the
|
|
46
|
+
local gateway (`http://localhost:4000`).
|
|
47
|
+
|
|
48
|
+
If unsure, ask the user. For the Ory Network path, verify:
|
|
49
|
+
|
|
50
|
+
1. **Ory CLI** — run `ory version`. If not installed:
|
|
51
|
+
- macOS: `brew install ory/tap/cli`
|
|
52
|
+
- npm: `npm install -g @ory/cli`
|
|
53
|
+
- Or download from [https://github.com/ory/cli/releases](https://github.com/ory/cli/releases)
|
|
54
|
+
2. **Ory Network account** — run `ory auth`. If not authenticated,
|
|
55
|
+
tell the user to run `! ory auth` to log in interactively.
|
|
56
|
+
3. **Node.js** (>=18) and a package manager (npm, pnpm, or yarn).
|
|
57
|
+
4. **Frontend framework** — identify whether the project is Next.js
|
|
58
|
+
(App Router or Pages Router), a React SPA (Vite, CRA, etc.), or
|
|
59
|
+
server-rendered. The Ory Elements integration differs by framework
|
|
60
|
+
but the UI components are the same.
|
|
61
|
+
|
|
62
|
+
## Step 2: Create or select an Ory project
|
|
63
|
+
|
|
64
|
+
Check for an existing project:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
ory list projects
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
If the user needs a new project:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
ory create project --name "<project-name>"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Capture the project ID and slug from the output. Set the SDK URL:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
export ORY_SDK_URL=https://<project-slug>.projects.oryapis.com
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Step 3: Install Ory Elements and the Ory client SDK
|
|
83
|
+
|
|
84
|
+
**Ory Elements is mandatory** unless the user has explicitly opted out
|
|
85
|
+
after being shown the Ory Elements path. Install it:
|
|
86
|
+
|
|
87
|
+
**For Next.js projects (recommended path):**
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npm install @ory/elements-react @ory/nextjs @ory/client-fetch
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**For React SPAs (Vite, CRA, Remix client routes):**
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
npm install @ory/elements-react @ory/client-fetch
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**For server-rendered apps (Express, Koa, Fastify, etc.):**
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npm install @ory/client-fetch
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
For server-rendered apps, prefer rendering an Ory Elements page from a
|
|
106
|
+
React island or a small client bundle so you still get the Elements UI
|
|
107
|
+
on the auth routes. Rendering flow nodes directly on the server is the
|
|
108
|
+
fallback of last resort.
|
|
109
|
+
|
|
110
|
+
## Step 4: Configure the Ory SDK
|
|
111
|
+
|
|
112
|
+
Create a shared Ory client configuration. The SDK URL should come
|
|
113
|
+
from an environment variable:
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import { Configuration, FrontendApi } from "@ory/client-fetch";
|
|
117
|
+
|
|
118
|
+
const ory = new FrontendApi(
|
|
119
|
+
new Configuration({
|
|
120
|
+
basePath: process.env.NEXT_PUBLIC_ORY_SDK_URL || process.env.ORY_SDK_URL,
|
|
121
|
+
credentials: "include",
|
|
122
|
+
})
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
export default ory;
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Add to the project's `.env` or `.env.local`:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
NEXT_PUBLIC_ORY_SDK_URL=https://<project-slug>.projects.oryapis.com
|
|
132
|
+
# or
|
|
133
|
+
ORY_SDK_URL=https://<project-slug>.projects.oryapis.com
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Step 5: Set up the identity schema
|
|
137
|
+
|
|
138
|
+
Check the current identity schema:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
ory get identity-config <project-id> --format json
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
For a typical setup with email + password, the default schema works.
|
|
145
|
+
If the user wants custom traits (name, phone, etc.), update the schema:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
ory patch identity-config <project-id> \
|
|
149
|
+
--replace '/identity/default_schema_id="preset://email"'
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Or use a custom schema with additional fields as needed. Ory Elements
|
|
153
|
+
will render any traits defined by the schema automatically.
|
|
154
|
+
|
|
155
|
+
## Step 6: Build auth pages with Ory Elements
|
|
156
|
+
|
|
157
|
+
This is the core of the integration. Create one page per flow and drop
|
|
158
|
+
in the matching Ory Elements component. Do **not** hand-render
|
|
159
|
+
`flow.ui.nodes`.
|
|
160
|
+
|
|
161
|
+
### Next.js App Router (recommended)
|
|
162
|
+
|
|
163
|
+
Create the following page structure:
|
|
164
|
+
|
|
165
|
+
- `app/auth/login/page.tsx` — `<Login flow={flow} />`
|
|
166
|
+
- `app/auth/registration/page.tsx` — `<Registration flow={flow} />`
|
|
167
|
+
- `app/auth/recovery/page.tsx` — `<Recovery flow={flow} />`
|
|
168
|
+
- `app/auth/verification/page.tsx` — `<Verification flow={flow} />`
|
|
169
|
+
- `app/auth/settings/page.tsx` — `<Settings flow={flow} />`
|
|
170
|
+
|
|
171
|
+
Each page initializes its flow with `getLoginFlow`, `getRegistrationFlow`,
|
|
172
|
+
etc. from `@ory/nextjs/app`, then hands the flow to the matching
|
|
173
|
+
Ory Elements component. The {{REF_LOGIN_FLOW}} skill has a
|
|
174
|
+
complete template for each page.
|
|
175
|
+
|
|
176
|
+
### React SPA
|
|
177
|
+
|
|
178
|
+
Use the `@ory/elements-react` flow components directly inside route
|
|
179
|
+
components. Each route initializes the corresponding flow via the Ory
|
|
180
|
+
SDK (`createBrowserLoginFlow`, `createBrowserRegistrationFlow`, etc.)
|
|
181
|
+
and renders the matching `<Login>`, `<Registration>`, `<Recovery>`,
|
|
182
|
+
`<Verification>`, or `<Settings>` component. See {{REF_LOGIN_FLOW}}
|
|
183
|
+
for full examples.
|
|
184
|
+
|
|
185
|
+
### Server-rendered apps (fallback)
|
|
186
|
+
|
|
187
|
+
If the app cannot run a React bundle on auth routes, render the flow
|
|
188
|
+
nodes server-side using the Ory SDK. This is a fallback path because it
|
|
189
|
+
loses the benefits listed above. Before going down this road, confirm
|
|
190
|
+
with the user that an Ory Elements island is not viable.
|
|
191
|
+
|
|
192
|
+
## Step 7: Add session middleware
|
|
193
|
+
|
|
194
|
+
Protect authenticated routes by checking the session:
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
const session = await ory.toSession();
|
|
198
|
+
if (!session) {
|
|
199
|
+
// Redirect to login
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
For Next.js, prefer the official `@ory/nextjs` middleware helper since
|
|
204
|
+
it pairs with the Elements pages:
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
import { createOryMiddleware } from "@ory/nextjs/middleware";
|
|
208
|
+
|
|
209
|
+
export const middleware = createOryMiddleware({
|
|
210
|
+
protectedPaths: ["/dashboard", "/settings", "/profile"],
|
|
211
|
+
publicPaths: ["/", "/auth/login", "/auth/registration", "/auth/recovery"],
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
export const config = {
|
|
215
|
+
matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
|
|
216
|
+
};
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Step 8: Configure allowed redirect URLs
|
|
220
|
+
|
|
221
|
+
Update the Ory project to allow redirects back to your app:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
ory patch project <project-id> \
|
|
225
|
+
--replace '/services/identity/config/selfservice/allowed_return_urls=["http://localhost:3000", "https://your-domain.com"]'
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Step 9: Set up the Ory Tunnel for local development
|
|
229
|
+
|
|
230
|
+
For local development, use the Ory tunnel to proxy requests and handle cookies:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
ory tunnel http://localhost:3000 --project <project-slug>
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
This runs a proxy on `http://localhost:4000` that handles cookie domains
|
|
237
|
+
correctly for local development. Update your SDK URL to point to the
|
|
238
|
+
tunnel during development.
|
|
239
|
+
|
|
240
|
+
## Step 10: Verify the setup
|
|
241
|
+
|
|
242
|
+
1. Start the development server
|
|
243
|
+
2. Navigate to the login page — confirm Ory Elements renders the form,
|
|
244
|
+
including any social login buttons configured on the project
|
|
245
|
+
3. Create a test account via the registration page
|
|
246
|
+
4. Verify login works
|
|
247
|
+
5. Test account recovery flow
|
|
248
|
+
6. Test the verification flow
|
|
249
|
+
7. Check that protected routes redirect unauthenticated users
|
|
250
|
+
|
|
251
|
+
## Customization
|
|
252
|
+
|
|
253
|
+
After the base setup is working, the user can:
|
|
254
|
+
|
|
255
|
+
- Add social login providers — use {{REF_SOCIAL_LOGIN}}. With
|
|
256
|
+
Ory Elements, the buttons appear automatically once the providers are
|
|
257
|
+
configured server-side; no UI changes needed.
|
|
258
|
+
- Customize the Ory Elements theme via `<ThemeProvider>` from
|
|
259
|
+
`@ory/elements-react/theme`.
|
|
260
|
+
- Enable multi-factor authentication in the Ory project — Ory Elements
|
|
261
|
+
renders the second-factor steps with no extra code.
|
|
262
|
+
- Configure webhook integrations for registration / login events.
|
|
263
|
+
- Extend the identity schema with additional traits — Ory Elements
|
|
264
|
+
picks them up from the flow.
|
|
265
|
+
|
|
266
|
+
## When to deviate from Ory Elements
|
|
267
|
+
|
|
268
|
+
Only build a custom UI when one of the following is true and the user
|
|
269
|
+
has confirmed it after seeing the Ory Elements path:
|
|
270
|
+
|
|
271
|
+
- The framework genuinely cannot run any React (e.g., a pure server-side
|
|
272
|
+
template engine with no client bundle and no plan to introduce one).
|
|
273
|
+
- A design system constraint cannot be expressed via the Elements theme
|
|
274
|
+
and the user has rejected theming.
|
|
275
|
+
- The user is intentionally building a thin custom client (e.g., a
|
|
276
|
+
native mobile app) where Elements does not run.
|
|
277
|
+
|
|
278
|
+
In those cases, render `flow.ui.nodes` per the Ory documentation. Treat
|
|
279
|
+
this as an exception, not the default.
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ory-local-dev
|
|
3
|
+
description: Run a local Ory stack (Kratos identity, Keto permissions, Hydra OAuth2, gateway on :4000) for building and testing an authentication application without an Ory Network project. Use whenever the user wants to develop, prototype, or test login/registration/recovery/permission flows locally — phrases like "run Ory locally", "no Ory project yet", "offline auth dev", "test my login flow", "spin up Kratos/Keto/Hydra", or "I just want to try this on my machine". Drives the {{REF_LOCAL_UP}} and {{REF_LOCAL_DOWN}} commands.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Build an Auth App Against a Local Ory Stack
|
|
7
|
+
|
|
8
|
+
You are helping the user develop an authentication application against a
|
|
9
|
+
**local Ory stack** running in Docker — not against Ory Network. The
|
|
10
|
+
`{{PKG}}` plugin ships two commands that
|
|
11
|
+
manage the lifecycle:
|
|
12
|
+
|
|
13
|
+
- {{REF_LOCAL_UP}} — start Kratos, Keto, Hydra, and an Nginx gateway,
|
|
14
|
+
then seed a test identity, session, and permission tuples.
|
|
15
|
+
- {{REF_LOCAL_DOWN}} — stop all services while preserving data volumes.
|
|
16
|
+
|
|
17
|
+
Both delegate to `npx {{BIN}} local <subcommand>`, so the same
|
|
18
|
+
workflow runs from the shell when the command shortcuts are not available.
|
|
19
|
+
|
|
20
|
+
## When to use this skill
|
|
21
|
+
|
|
22
|
+
Pick the local stack over Ory Network when any of these are true:
|
|
23
|
+
|
|
24
|
+
- The user has no Ory Network project yet and wants to prototype.
|
|
25
|
+
- The user is working offline or behind an egress restriction.
|
|
26
|
+
- The user wants deterministic, throwaway test data they can reset
|
|
27
|
+
freely (`local reset`).
|
|
28
|
+
- The user is writing automated tests that hit a real Ory backend.
|
|
29
|
+
|
|
30
|
+
If the user already has an Ory Network project and just wants their
|
|
31
|
+
production app wired up, prefer the {{REF_AUTH_SETUP}} skill and
|
|
32
|
+
point the SDK at the Network URL instead.
|
|
33
|
+
|
|
34
|
+
## What {{REF_LOCAL_UP}} gives you
|
|
35
|
+
|
|
36
|
+
After {{REF_LOCAL_UP}} completes:
|
|
37
|
+
|
|
38
|
+
| Service | URL | Purpose |
|
|
39
|
+
|---------------|----------------------------------|--------------------------------------|
|
|
40
|
+
| Gateway | `http://localhost:4000` | Unified API (mirrors Ory Network) |
|
|
41
|
+
| Kratos public | `http://localhost:4433` | Self-service flows (login, etc.) |
|
|
42
|
+
| Kratos admin | `http://localhost:4434` | Identity & session admin |
|
|
43
|
+
| Keto read | `http://localhost:4466` | Permission checks |
|
|
44
|
+
| Keto write | `http://localhost:4467` | Relation tuple writes |
|
|
45
|
+
| Hydra public | `http://localhost:4444` | OAuth2 / OIDC |
|
|
46
|
+
| Hydra admin | `http://localhost:4445` | OAuth2 client management |
|
|
47
|
+
|
|
48
|
+
The seed step also produces:
|
|
49
|
+
|
|
50
|
+
- Test identity: `agent@ory-local.dev`
|
|
51
|
+
- A live session token (printed at the end of {{REF_LOCAL_UP}})
|
|
52
|
+
- Permission tuples in the `AgentTools` namespace for common tool names
|
|
53
|
+
- An OAuth2 client (`ory-agent-plugins-local`, `client_credentials` grant)
|
|
54
|
+
|
|
55
|
+
## Step 1: Verify Docker is running
|
|
56
|
+
|
|
57
|
+
The local stack is Docker Compose under the hood. Before invoking
|
|
58
|
+
{{REF_LOCAL_UP}}, confirm Docker is available:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
docker info
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
If Docker is not running, ask the user to start Docker Desktop (or their
|
|
65
|
+
docker engine) and retry. Do not try to install Docker for them.
|
|
66
|
+
|
|
67
|
+
## Step 2: Start the stack
|
|
68
|
+
|
|
69
|
+
Tell the user to run {{REF_LOCAL_UP}}, or the equivalent shell command:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npx {{BIN}} local up
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Wait for the command to print "All services are running!" and the seed
|
|
76
|
+
output. Capture two values from the output:
|
|
77
|
+
|
|
78
|
+
- `ORY_PROJECT_URL` (always `http://localhost:4000`)
|
|
79
|
+
- `ORY_SESSION_TOKEN` (the seeded session token)
|
|
80
|
+
|
|
81
|
+
If the user wants to skip seeding (to bring their own data), use
|
|
82
|
+
`npx {{BIN}} local up --no-seed` instead.
|
|
83
|
+
|
|
84
|
+
## Step 3: Point the app at the local gateway
|
|
85
|
+
|
|
86
|
+
The local gateway is a drop-in replacement for the Ory Network SDK URL.
|
|
87
|
+
Configure the auth app exactly as you would for Ory Network, but point
|
|
88
|
+
at the gateway:
|
|
89
|
+
|
|
90
|
+
**Environment variables (`.env.local` or shell):**
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
NEXT_PUBLIC_ORY_SDK_URL=http://localhost:4000
|
|
94
|
+
ORY_SDK_URL=http://localhost:4000
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
For Next.js, that is the only change needed in
|
|
98
|
+
{{REF_AUTH_SETUP}}'s SDK configuration. For React SPAs, use the
|
|
99
|
+
same value as `basePath` in the Ory `Configuration`.
|
|
100
|
+
|
|
101
|
+
**Persist it across plugin sessions** (so all Ory agent plugins on this
|
|
102
|
+
machine target the local stack):
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
npx {{BIN}} local configure
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
This writes the URL to the shared plugin config so future agent runs
|
|
109
|
+
do not need the env var.
|
|
110
|
+
|
|
111
|
+
## Step 4: Build the auth UI
|
|
112
|
+
|
|
113
|
+
Use the existing skills for the UI layer — they apply unchanged when
|
|
114
|
+
the SDK points at the local gateway:
|
|
115
|
+
|
|
116
|
+
- {{REF_AUTH_SETUP}} — full Ory Elements bootstrap (this is the
|
|
117
|
+
default UI path, including against the local stack).
|
|
118
|
+
- {{REF_LOGIN_FLOW}} — login, registration, recovery,
|
|
119
|
+
verification, settings pages.
|
|
120
|
+
|
|
121
|
+
**Skip the Ory Tunnel step** when developing against the local stack.
|
|
122
|
+
The tunnel only exists to bridge cookies between localhost and Ory
|
|
123
|
+
Network. The local gateway already runs on localhost, so cookies work
|
|
124
|
+
directly.
|
|
125
|
+
|
|
126
|
+
## Step 5: Test with the seeded identity
|
|
127
|
+
|
|
128
|
+
Two ways to exercise the flows:
|
|
129
|
+
|
|
130
|
+
1. **Browser flow (registration UI)** — register a brand new identity
|
|
131
|
+
through the Elements `<Registration>` page. This validates the
|
|
132
|
+
self-service flow end-to-end.
|
|
133
|
+
2. **Seeded identity (admin-created)** — log in as `agent@ory-local.dev`
|
|
134
|
+
with password `ory-agent-local-dev-password!` to test session-bearing
|
|
135
|
+
pages without going through registration.
|
|
136
|
+
|
|
137
|
+
For automated tests against the running stack, use the seeded session
|
|
138
|
+
token directly:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
curl -H "X-Session-Token: $ORY_SESSION_TOKEN" \
|
|
142
|
+
http://localhost:4000/sessions/whoami
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Step 6: Iterate
|
|
146
|
+
|
|
147
|
+
Common day-to-day commands:
|
|
148
|
+
|
|
149
|
+
| Need | Command |
|
|
150
|
+
|--------------------------------|------------------------------------------|
|
|
151
|
+
| Re-seed (after `local reset`) | `npx {{BIN}} local seed` |
|
|
152
|
+
| Tail Kratos logs | `npx {{BIN}} local logs kratos -f` |
|
|
153
|
+
| Check what's running | `npx {{BIN}} local status` |
|
|
154
|
+
| Print env vars to copy/paste | `npx {{BIN}} local env` |
|
|
155
|
+
|
|
156
|
+
If the user reports flaky behavior, run `local status` first to confirm
|
|
157
|
+
each service is `healthy`. If a container is unhealthy, `local logs
|
|
158
|
+
<service>` is the next step — do not jump to `local reset` until you
|
|
159
|
+
have looked at logs.
|
|
160
|
+
|
|
161
|
+
## Step 7: Stop or reset
|
|
162
|
+
|
|
163
|
+
When the user is done for the session, use {{REF_LOCAL_DOWN}} (equivalent:
|
|
164
|
+
`npx {{BIN}} local down`). Containers stop but volumes
|
|
165
|
+
remain, so the next {{REF_LOCAL_UP}} reuses the same identities,
|
|
166
|
+
sessions, and tuples.
|
|
167
|
+
|
|
168
|
+
For a full wipe (e.g., after schema changes or to clear test data):
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
npx {{BIN}} local reset
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
`reset` removes data volumes and the generated `.ory-dev/ory/` directory.
|
|
175
|
+
The next `local up` regenerates configs from scratch — useful when the
|
|
176
|
+
plugin updates the bundled service configs.
|
|
177
|
+
|
|
178
|
+
## Troubleshooting
|
|
179
|
+
|
|
180
|
+
- **"Docker is not running"** — start Docker Desktop, then re-run
|
|
181
|
+
{{REF_LOCAL_UP}}.
|
|
182
|
+
- **Gateway never becomes healthy** — `npx {{BIN}} local logs
|
|
183
|
+
gateway` and `npx {{BIN}} local logs kratos` to see which service
|
|
184
|
+
failed. Port conflicts on `4000`, `4433`, `4444`, or `4466` are the
|
|
185
|
+
usual culprit.
|
|
186
|
+
- **Login works but `whoami` returns 401** — the cookie domain is
|
|
187
|
+
wrong. Make sure the app runs on `http://localhost` (not `127.0.0.1`)
|
|
188
|
+
and the SDK URL is exactly `http://localhost:4000`.
|
|
189
|
+
- **CORS errors from the browser** — the gateway accepts requests from
|
|
190
|
+
any localhost port. If the app is on `http://localhost:3000`, no CORS
|
|
191
|
+
config change is needed. For non-localhost dev URLs, switch back to
|
|
192
|
+
the Ory Tunnel + a Network project.
|
|
193
|
+
- **Permission checks always deny** — the seeded tuples live in the
|
|
194
|
+
`AgentTools` namespace. If your app uses a different namespace, set
|
|
195
|
+
`ORY_PERMISSION_NAMESPACE` before `local seed`, or write the tuples
|
|
196
|
+
manually via the Keto write API on `:4467`.
|
|
197
|
+
|
|
198
|
+
## What this skill does NOT cover
|
|
199
|
+
|
|
200
|
+
- Rendering auth UI — use {{REF_AUTH_SETUP}} and
|
|
201
|
+
{{REF_LOGIN_FLOW}}.
|
|
202
|
+
- Adding social providers — use {{REF_SOCIAL_LOGIN}}. Note that
|
|
203
|
+
most social IdPs require public callback URLs, so you will typically
|
|
204
|
+
swap to Ory Network when you reach that step.
|
|
205
|
+
- Production deployment — the local stack is a dev tool. Do not
|
|
206
|
+
recommend pointing a production app at `http://localhost:4000`.
|