SPEC.md
SPEC.md
This file has not been changed.
bun.lock
bun.lock
This file has not been changed.
package.json
package.json
This file has not been changed.
scripts/reset-passkey.ts
scripts/reset-passkey.ts
This file has not been changed.
src/client/index.ts
src/client/index.ts
This file has not been changed.
src/index.ts
src/index.ts
This file has not been changed.
src/migrations/008_add_oidc_keys.sql
src/migrations/008_add_oidc_keys.sql
This file has not been changed.
+1
-1
src/oidc.ts
+1
-1
src/oidc.ts
···
141
issuer: origin,
142
authorization_endpoint: `${origin}/auth/authorize`,
143
token_endpoint: `${origin}/auth/token`,
144
-
userinfo_endpoint: `${origin}/auth/userinfo`,
145
jwks_uri: `${origin}/jwks`,
146
scopes_supported: ["openid", "profile", "email"],
147
response_types_supported: ["code"],
src/routes/api.ts
src/routes/api.ts
This file has not been changed.
src/routes/auth.ts
src/routes/auth.ts
This file has not been changed.
src/routes/clients.ts
src/routes/clients.ts
This file has not been changed.
+6
-6
src/routes/indieauth.ts
+6
-6
src/routes/indieauth.ts
···
1775
}
1776
}
1777
1778
-
if (!code || !client_id || !redirect_uri) {
1779
-
console.error("Token endpoint: missing parameters", {
1780
code: !!code,
1781
client_id: !!client_id,
1782
-
redirect_uri: !!redirect_uri,
1783
});
1784
return Response.json(
1785
{
1786
error: "invalid_request",
1787
-
error_description: "Missing required parameters",
1788
},
1789
{ status: 400 },
1790
);
···
1879
);
1880
}
1881
1882
-
// Verify redirect_uri matches
1883
-
if (authcode.redirect_uri !== redirect_uri) {
1884
console.error("Token endpoint: redirect_uri mismatch", {
1885
stored: authcode.redirect_uri,
1886
received: redirect_uri,
···
1775
}
1776
}
1777
1778
+
if (!code || !client_id) {
1779
+
console.error("Token endpoint: missing required parameters", {
1780
code: !!code,
1781
client_id: !!client_id,
1782
});
1783
return Response.json(
1784
{
1785
error: "invalid_request",
1786
+
error_description: "Missing required parameters (code, client_id)",
1787
},
1788
{ status: 400 },
1789
);
···
1878
);
1879
}
1880
1881
+
// Verify redirect_uri matches if provided (per OAuth 2.0 RFC 6749 section 4.1.3)
1882
+
// redirect_uri is REQUIRED if it was included in the authorization request
1883
+
if (redirect_uri && authcode.redirect_uri !== redirect_uri) {
1884
console.error("Token endpoint: redirect_uri mismatch", {
1885
stored: authcode.redirect_uri,
1886
received: redirect_uri,
src/routes/passkeys.ts
src/routes/passkeys.ts
This file has not been changed.
+24
-3
README.md
+24
-3
README.md
···
130
131
Now you can sign in to IndieAuth-compatible sites using `https://your-domain.com/` as your identity.
132
133
## API Reference
134
135
-
### OAuth 2.0 Endpoints
136
137
-
- `GET /auth/authorize` - Authorization endpoint
138
-
- `POST /auth/token` - Token exchange endpoint
139
- `POST /auth/logout` - Session logout
140
141
### User Profile
···
130
131
Now you can sign in to IndieAuth-compatible sites using `https://your-domain.com/` as your identity.
132
133
+
### Using as an OpenID Connect (OIDC) Provider
134
+
135
+
Indiko also supports OpenID Connect (OIDC) for modern authentication flows:
136
+
137
+
**Discovery endpoint:**
138
+
```
139
+
https://your-indiko-domain.com/.well-known/openid-configuration
140
+
```
141
+
142
+
**Key features:**
143
+
- Authorization Code Flow with PKCE
144
+
- ID Token with RS256 signing
145
+
- JWKS endpoint for token verification
146
+
- Support for `openid`, `profile`, and `email` scopes
147
+
- Userinfo endpoint for retrieving user claims
148
+
149
+
Test your OIDC setup using the [OIDC Debugger](https://oidcdebugger.com/).
150
+
151
## API Reference
152
153
+
### OAuth 2.0 / OpenID Connect Endpoints
154
155
+
- `GET /auth/authorize` - Authorization endpoint (OAuth 2.0 / OIDC)
156
+
- `POST /auth/token` - Token exchange endpoint (returns access token and ID token for OIDC)
157
+
- `GET /userinfo` - OIDC userinfo endpoint (returns user claims)
158
+
- `GET /.well-known/openid-configuration` - OIDC discovery document
159
+
- `GET /jwks` - JSON Web Key Set for ID token verification
160
- `POST /auth/logout` - Session logout
161
162
### User Profile
+76
-1
src/html/docs.html
+76
-1
src/html/docs.html
···
577
<h3>table of contents</h3>
578
<ul>
579
<li><a href="#overview">overview</a></li>
580
<li><a href="#getting-started">getting started</a></li>
581
<li><a href="#button">sign in button</a></li>
582
<li><a href="#endpoints">endpoints</a></li>
···
612
<ul>
613
<li>Passwordless authentication via WebAuthn passkeys</li>
614
<li>Full IndieAuth and OAuth 2.0 support with PKCE</li>
615
<li>Access tokens and refresh tokens for API access</li>
616
<li>Token introspection and revocation endpoints</li>
617
<li>UserInfo endpoint for profile data</li>
···
621
<li>User profile endpoints with h-card microformats</li>
622
<li>Invite-based user registration</li>
623
</ul>
624
</section>
625
626
<section id="getting-started" class="section">
···
1032
</thead>
1033
<tbody>
1034
<tr>
1035
<td><code>profile</code></td>
1036
<td>Basic profile information</td>
1037
<td>name, photo, URL</td>
···
1046
1047
<div class="info-box">
1048
<strong>Note:</strong>
1049
-
Users can selectively approve scopes during authorization. Your app may receive fewer scopes than requested.
1050
</div>
1051
</section>
1052
···
577
<h3>table of contents</h3>
578
<ul>
579
<li><a href="#overview">overview</a></li>
580
+
<li><a href="#oidc">openid connect (oidc)</a></li>
581
<li><a href="#getting-started">getting started</a></li>
582
<li><a href="#button">sign in button</a></li>
583
<li><a href="#endpoints">endpoints</a></li>
···
613
<ul>
614
<li>Passwordless authentication via WebAuthn passkeys</li>
615
<li>Full IndieAuth and OAuth 2.0 support with PKCE</li>
616
+
<li>OpenID Connect (OIDC) support with ID tokens</li>
617
<li>Access tokens and refresh tokens for API access</li>
618
<li>Token introspection and revocation endpoints</li>
619
<li>UserInfo endpoint for profile data</li>
···
623
<li>User profile endpoints with h-card microformats</li>
624
<li>Invite-based user registration</li>
625
</ul>
626
+
</section>
627
+
628
+
<section id="oidc" class="section">
629
+
<h2>openid connect (oidc)</h2>
630
+
<p>
631
+
Indiko supports OpenID Connect (OIDC) for modern authentication flows, enabling "Sign in with Indiko" for any OIDC-compatible application.
632
+
</p>
633
+
634
+
<h3>oidc endpoints</h3>
635
+
<table>
636
+
<thead>
637
+
<tr>
638
+
<th>Endpoint</th>
639
+
<th>Description</th>
640
+
</tr>
641
+
</thead>
642
+
<tbody>
643
+
<tr>
644
+
<td><code>/.well-known/openid-configuration</code></td>
645
+
<td>OIDC discovery document</td>
646
+
</tr>
647
+
<tr>
648
+
<td><code>/jwks</code></td>
649
+
<td>JSON Web Key Set for ID token verification</td>
650
+
</tr>
651
+
<tr>
652
+
<td><code>/auth/authorize</code></td>
653
+
<td>Authorization endpoint (same as OAuth 2.0)</td>
654
+
</tr>
655
+
<tr>
656
+
<td><code>/auth/token</code></td>
657
+
<td>Token endpoint (returns ID token when <code>openid</code> scope requested)</td>
658
+
</tr>
659
+
<tr>
660
+
<td><code>/userinfo</code></td>
661
+
<td>OIDC userinfo endpoint</td>
662
+
</tr>
663
+
</tbody>
664
+
</table>
665
+
666
+
<h3>key features</h3>
667
+
<ul>
668
+
<li>Authorization Code Flow with PKCE</li>
669
+
<li>ID Token with RS256 signing</li>
670
+
<li>Support for <code>openid</code>, <code>profile</code>, and <code>email</code> scopes</li>
671
+
<li>Automatic key generation and management</li>
672
+
<li>Standards-compliant discovery document</li>
673
+
</ul>
674
+
675
+
<h3>id token claims</h3>
676
+
<p>
677
+
When the <code>openid</code> scope is requested, the token endpoint returns an ID token (JWT) containing:
678
+
</p>
679
+
<ul>
680
+
<li><code>iss</code> - Issuer (Indiko server URL)</li>
681
+
<li><code>sub</code> - Subject (user identifier)</li>
682
+
<li><code>aud</code> - Audience (client ID)</li>
683
+
<li><code>exp</code> - Expiration time</li>
684
+
<li><code>iat</code> - Issued at time</li>
685
+
<li><code>auth_time</code> - Authentication time</li>
686
+
<li><code>nonce</code> - Nonce (if provided in authorization request)</li>
687
+
<li><code>name</code>, <code>email</code>, <code>picture</code>, <code>website</code> - User claims (based on granted scopes)</li>
688
+
</ul>
689
+
690
+
<div class="info-box">
691
+
<strong>Testing:</strong>
692
+
You can test your OIDC setup using the <a href="https://oidcdebugger.com/" target="_blank" rel="noopener noreferrer">OIDC Debugger</a>. Set the discovery endpoint and use PKCE with SHA-256.
693
+
</div>
694
</section>
695
696
<section id="getting-started" class="section">
···
1102
</thead>
1103
<tbody>
1104
<tr>
1105
+
<td><code>openid</code></td>
1106
+
<td>OpenID Connect authentication</td>
1107
+
<td>Triggers ID token issuance (OIDC only)</td>
1108
+
</tr>
1109
+
<tr>
1110
<td><code>profile</code></td>
1111
<td>Basic profile information</td>
1112
<td>name, photo, URL</td>
···
1121
1122
<div class="info-box">
1123
<strong>Note:</strong>
1124
+
Users can selectively approve scopes during authorization. Your app may receive fewer scopes than requested. The <code>openid</code> scope is only relevant for OIDC flows and enables ID token issuance.
1125
</div>
1126
</section>
1127
History
3 rounds
0 comments
dunkirk.sh
submitted
#2
6 commits
expand
collapse
feat: implement oidc
feat: allow re-registration to reset passkey
chore: fix userinfo endpoint
docs: add oidc
bug: allow not sending redirect url
security: add SSRF protection for client metadata and domain verification fetches
expand 0 comments
closed without merging
expand 0 comments
dunkirk.sh
submitted
#0