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
141
issuer: origin,
142
142
authorization_endpoint: `${origin}/auth/authorize`,
143
143
token_endpoint: `${origin}/auth/token`,
144
-
userinfo_endpoint: `${origin}/auth/userinfo`,
144
+
userinfo_endpoint: `${origin}/userinfo`,
145
145
jwks_uri: `${origin}/jwks`,
146
146
scopes_supported: ["openid", "profile", "email"],
147
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
1775
}
1776
1776
}
1777
1777
1778
-
if (!code || !client_id || !redirect_uri) {
1779
-
console.error("Token endpoint: missing parameters", {
1778
+
if (!code || !client_id) {
1779
+
console.error("Token endpoint: missing required parameters", {
1780
1780
code: !!code,
1781
1781
client_id: !!client_id,
1782
-
redirect_uri: !!redirect_uri,
1783
1782
});
1784
1783
return Response.json(
1785
1784
{
1786
1785
error: "invalid_request",
1787
-
error_description: "Missing required parameters",
1786
+
error_description: "Missing required parameters (code, client_id)",
1788
1787
},
1789
1788
{ status: 400 },
1790
1789
);
···
1879
1878
);
1880
1879
}
1881
1880
1882
-
// Verify redirect_uri matches
1883
-
if (authcode.redirect_uri !== redirect_uri) {
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
1884
console.error("Token endpoint: redirect_uri mismatch", {
1885
1885
stored: authcode.redirect_uri,
1886
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
130
131
131
Now you can sign in to IndieAuth-compatible sites using `https://your-domain.com/` as your identity.
132
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
+
133
151
## API Reference
134
152
135
-
### OAuth 2.0 Endpoints
153
+
### OAuth 2.0 / OpenID Connect Endpoints
136
154
137
-
- `GET /auth/authorize` - Authorization endpoint
138
-
- `POST /auth/token` - Token exchange endpoint
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
139
160
- `POST /auth/logout` - Session logout
140
161
141
162
### User Profile
+76
-1
src/html/docs.html
+76
-1
src/html/docs.html
···
577
577
<h3>table of contents</h3>
578
578
<ul>
579
579
<li><a href="#overview">overview</a></li>
580
+
<li><a href="#oidc">openid connect (oidc)</a></li>
580
581
<li><a href="#getting-started">getting started</a></li>
581
582
<li><a href="#button">sign in button</a></li>
582
583
<li><a href="#endpoints">endpoints</a></li>
···
612
613
<ul>
613
614
<li>Passwordless authentication via WebAuthn passkeys</li>
614
615
<li>Full IndieAuth and OAuth 2.0 support with PKCE</li>
616
+
<li>OpenID Connect (OIDC) support with ID tokens</li>
615
617
<li>Access tokens and refresh tokens for API access</li>
616
618
<li>Token introspection and revocation endpoints</li>
617
619
<li>UserInfo endpoint for profile data</li>
···
621
623
<li>User profile endpoints with h-card microformats</li>
622
624
<li>Invite-based user registration</li>
623
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>
624
694
</section>
625
695
626
696
<section id="getting-started" class="section">
···
1032
1102
</thead>
1033
1103
<tbody>
1034
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>
1035
1110
<td><code>profile</code></td>
1036
1111
<td>Basic profile information</td>
1037
1112
<td>name, photo, URL</td>
···
1046
1121
1047
1122
<div class="info-box">
1048
1123
<strong>Note:</strong>
1049
-
Users can selectively approve scopes during authorization. Your app may receive fewer scopes than requested.
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.
1050
1125
</div>
1051
1126
</section>
1052
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