npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@aginix/adonis-ally-oidc

v0.1.0

Published

OpenID Connect (OIDC) driver for AdonisJS Ally — discovery, ID-token verification, PKCE, nonce, and RP-initiated logout. Built for Keycloak and any OIDC provider.

Downloads

46

Readme

@aginix/adonis-ally-oidc

Generic OpenID Connect driver for AdonisJS Ally — discovery, ID-token verification, PKCE, nonce, and RP-initiated logout. Built for Keycloak and any OIDC-compliant provider.

npm version License: MIT Node >= 24

@adonisjs/ally ships drivers for Google, GitHub, Discord, and friends, but no generic OpenID Connect driver. This package fills that gap: give it an issuer and it discovers the endpoints, verifies the id_token (signature + claims + nonce), runs PKCE, and exposes RP-initiated logout — all behind ally's familiar ally.use('...') API. Works with Keycloak (first-class), Auth0, Okta, Microsoft Entra ID, Zitadel, Google, and any spec-compliant provider.

Features

A bare OAuth2 driver can call a userinfo endpoint, but it never proves who issued the token. This driver does the OIDC-specific work:

| Feature | What it does | |---|---| | Discovery | issuer.well-known/openid-configuration → endpoints + JWKS, resolved once at boot | | ID-token verification | RS256/ES256/… signature via remote JWKS, plus iss, aud/azp, exp/iat/nbf (clock skew), and nonce — strict by default | | PKCE | S256, on by default | | Nonce | issued in an encrypted cookie, verified against the id_token (replay protection) | | RP-Initiated Logout | redirect to the provider's end_session_endpoint with id_token_hint + post_logout_redirect_uri | | Typed | ally.use('keycloak') is fully typed, including the returned user and tokens |

Requirements

  • Node.js >= 24
  • @adonisjs/ally ^6.3.0 and @adonisjs/core ^7 (peer dependencies)

Installation

npm i @aginix/adonis-ally-oidc
node ace configure @aginix/adonis-ally-oidc

Install and configure @adonisjs/ally first, if you haven't:

node ace add @adonisjs/ally

node ace configure adds env validations and prints the config snippet. Set your secrets:

# .env
OIDC_ISSUER=https://sso.example.com/realms/myrealm
OIDC_CLIENT_ID=my-app
OIDC_CLIENT_SECRET=super-secret

Configure the provider

Register an oidc(...) provider in config/ally.ts:

import env from '#start/env'
import { defineConfig } from '@adonisjs/ally'
import { oidc } from '@aginix/adonis-ally-oidc'

export default defineConfig({
  keycloak: oidc({
    issuer: env.get('OIDC_ISSUER'),
    clientId: env.get('OIDC_CLIENT_ID'),
    clientSecret: env.get('OIDC_CLIENT_SECRET'),
    callbackUrl: 'http://localhost:3333/auth/keycloak/callback',
    postLogoutRedirectUri: 'http://localhost:3333',
  }),
})

Discovery and the JWKS are resolved once at boot, so a wrong or unreachable issuer fails startup with a clear error.

Usage

import router from '@adonisjs/core/services/router'

// 1) Send the user to the provider
router.get('/auth/keycloak/redirect', ({ ally }) => {
  return ally.use('keycloak').redirect()
})

// 2) Handle the callback
router.get('/auth/keycloak/callback', async ({ ally, auth, response, session }) => {
  const kc = ally.use('keycloak')

  if (kc.accessDenied()) return 'You cancelled the login'
  if (kc.stateMisMatch()) return 'Request expired, retry'
  if (kc.hasError()) return kc.getError()

  const oidcUser = await kc.user()
  // oidcUser.id            -> the "sub" claim
  // oidcUser.email, .name, .nickName (preferred_username)
  // oidcUser.original      -> full verified claims (e.g. Keycloak realm_access.roles)
  // oidcUser.token.idToken -> raw id_token, store it for logout

  // `externalId` is your own column; linking by the stable `sub` survives
  // email changes. (The demo app links by email — either works.)
  const user = await User.firstOrCreate(
    { externalId: oidcUser.id },
    { email: oidcUser.email!, fullName: oidcUser.name }
  )
  await auth.use('web').login(user)

  session.put('id_token', oidcUser.token.idToken)
  return response.redirect('/dashboard')
})

// 3) Log out locally and at the provider (RP-initiated logout)
router.get('/auth/keycloak/logout', async ({ ally, auth, session }) => {
  const idTokenHint = session.get('id_token')
  await auth.use('web').logout()
  session.forget('id_token')

  return ally.use('keycloak').logout({ idTokenHint })
})

logout(...) redirects to the provider's end_session_endpoint. Register your postLogoutRedirectUri with the provider (Keycloak: client → Valid post logout redirect URIs). Keycloak v18+ requires the id_token_hint (or a registered post-logout URI + client_id, which this driver always sends).

How id-token verification works

On the callback, user() exchanges the code at the token endpoint and then verifies the returned id_token with jose: the signature against the provider's JWKS (asymmetric algorithms only — none and symmetric HS* are rejected), plus iss, aud/azp, exp/iat/nbf (with optional clock skew), and the nonce issued during the redirect. Identity is taken from these verified claims, never from an unverified source.

Example app

See apps/demo in the repo for a complete Inertia/React integration: a "Login with Keycloak" button, the callback wiring, and RP-initiated logout.

Keycloak notes

  • issuer is https://{host}/realms/{realm} (Keycloak ≥ 17 — older builds use /auth/realms/{realm}).
  • Roles live in realm_access.roles / resource_access.{client}.roles on the verified claims — read them from oidcUser.original.
  • Map extra claims (picture, groups) with Keycloak client scopes / protocol mappers so they land in the id_token.

Configuration reference

| Option | Default | Description | |---|---|---| | clientId, clientSecret, callbackUrl | — | Standard OAuth2 client credentials | | issuer | — | Issuer URL for discovery | | scopes | ['openid','profile','email'] | Requested scopes | | usePKCE | true | PKCE (S256) | | postLogoutRedirectUri | — | Default redirect after logout | | fetchUserInfo | false | Also call userinfo and merge (its sub must match the id_token) | | clockTolerance | 0 | Skew tolerance for id_token time claims (seconds or '30s') | | cookieName | 'oidc' | Cookie-name prefix (set per provider if you register several) | | extraAuthParams | — | Extra static auth-request params, e.g. { prompt: 'login' } |

Escape hatches

  • Skip discovery — pass authorizeUrl + accessTokenUrl + jwksUri (+ optional userInfoUrl, endSessionEndpoint) explicitly.
  • Restrict / pin algorithmsidTokenSigningAlgs: ['RS256'].
  • Disable verificationverifyIdToken: false decodes the id_token without checking its signature. Only do this behind a fully trusted channel; it removes the package's core security guarantee.

Contributing

This package lives in the adonis-vulcan monorepo (pnpm, Node >= 24). Issues and PRs welcome.

pnpm install
pnpm --filter @aginix/adonis-ally-oidc test     # lint + japa + coverage
pnpm --filter @aginix/adonis-ally-oidc build

License

MIT © Aginix. See LICENSE.md.