Install
$ agentstack add skill-thunder-id-skills-integrate-oidc ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
ThunderID — Generic OIDC Integration
Assumes ThunderID is running at https://localhost:8090. If not, run /setup-thunderid first.
ThunderID is a standard OpenID Connect provider. Its discovery document is at:
https://localhost:8090/.well-known/openid-configuration
OIDC endpoints:
| Endpoint | URL | |----------|-----| | Discovery | https://localhost:8090/.well-known/openid-configuration | | Authorization | https://localhost:8090/oauth2/authorize | | Token | https://localhost:8090/oauth2/token | | Userinfo | https://localhost:8090/oauth2/userinfo | | JWKS | https://localhost:8090/oauth2/jwks | | End session | https://localhost:8090/oidc/logout |
Step 1 — Register an Application
Ask the developer to create an application in ThunderID and share the Client ID (and Client Secret for server-side apps) before continuing.
Guide them through these steps:
- Open
https://localhost:8090/consoleand sign in (default:admin/secret) - Navigate to Applications → New Application
- Fill in:
- Name: their app name
- Type: Single Page Application for browser apps; Web Application for server-side
- Authorized Redirect URL: their app's callback URL
- Click Create and copy the Client ID (and Client Secret for server-side apps)
Once they paste the values, use them in all subsequent steps. Do not use placeholders — wait for the real values.
Angular — oidc-client-ts
npm install oidc-client-ts
Create src/auth.ts:
import { UserManager, WebStorageStateStore } from 'oidc-client-ts'
export const userManager = new UserManager({
authority: 'https://localhost:8090',
client_id: '',
redirect_uri: `${window.location.origin}/callback`,
post_logout_redirect_uri: `${window.location.origin}`,
response_type: 'code',
scope: 'openid profile email',
userStore: new WebStorageStateStore({ store: window.localStorage }),
})
export const signIn = () => userManager.signinRedirect()
export const signOut = () => userManager.signoutRedirect()
export const getUser = () => userManager.getUser()
Callback handler at the /callback route:
import { userManager } from './auth'
await userManager.signinRedirectCallback()
window.location.replace('/')
Route guard:
import { inject } from '@angular/core'
import { CanActivateFn, Router } from '@angular/router'
import { getUser } from './auth'
export const authGuard: CanActivateFn = async () => {
const user = await getUser()
if (!user || user.expired) {
inject(Router).navigate(['/'])
return false
}
return true
}
SvelteKit — Auth.js
npm install @auth/sveltekit
src/auth.ts:
import { SvelteKitAuth } from '@auth/sveltekit'
export const { handle, signIn, signOut } = SvelteKitAuth({
providers: [
{
id: 'thunderid',
name: 'ThunderID',
type: 'oidc',
issuer: 'https://localhost:8090',
clientId: '',
clientSecret: '',
},
],
})
src/hooks.server.ts:
export { handle } from './auth'
Protect a route in +page.server.ts:
import { redirect } from '@sveltejs/kit'
import type { PageServerLoad } from './$types'
export const load: PageServerLoad = async (event) => {
const session = await event.locals.auth()
if (!session) throw redirect(303, '/')
return { session }
}
Sign-in / sign-out in a Svelte component:
import { signIn, signOut } from '@auth/sveltekit/client'
import { page } from '$app/stores'
{#if $page.data.session}
signOut()}>Sign Out
Signed in as {$page.data.session.user?.email}
{:else}
signIn('thunderid')}>Sign In
{/if}
Python — authlib
pip install authlib httpx
from authlib.integrations.httpx_client import AsyncOAuth2Client
client = AsyncOAuth2Client(
client_id='',
client_secret='',
redirect_uri='http://localhost:8000/callback',
)
# Discover endpoints
metadata = await client.load_server_metadata('https://localhost:8090/.well-known/openid-configuration')
# Start login
uri, state = client.create_authorization_url(metadata['authorization_endpoint'], scope='openid profile email')
# In the callback handler
token = await client.fetch_token(metadata['token_endpoint'], authorization_response=str(request.url))
userinfo = await client.get(metadata['userinfo_endpoint'])
Go — coreos/go-oidc
go get github.com/coreos/go-oidc/v3/oidc golang.org/x/oauth2
provider, err := oidc.NewProvider(ctx, "https://localhost:8090")
config := oauth2.Config{
ClientID: "",
ClientSecret: "",
RedirectURL: "http://localhost:8080/callback",
Endpoint: provider.Endpoint(),
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
}
// Start login
http.Redirect(w, r, config.AuthCodeURL(state), http.StatusFound)
// In /callback
token, err := config.Exchange(ctx, r.URL.Query().Get("code"))
idToken, err := provider.Verifier(&oidc.Config{ClientID: ""}).Verify(ctx, token.Extra("id_token").(string))
var claims struct {
Email string `json:"email"`
Name string `json:"name"`
}
idToken.Claims(&claims)
Troubleshooting
Certificate error — For browsers: visit https://localhost:8090 and accept the warning. For Node.js: add NODE_TLS_REJECT_UNAUTHORIZED=0 to .env.local (dev only). For Python: pass verify=False to the HTTP client (dev only). For Go: configure a custom TLS client.
CORS error — Ensure the redirect URI registered in the ThunderID console exactly matches the one used in code, including trailing slashes.
invalid_client — Double-check the Client ID and Client Secret.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: thunder-id
- Source: thunder-id/skills
- License: Apache-2.0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.