Skip to content

Add Dependabot for every example, build badges and the docs drift checklist - #43

Merged
pnzrr merged 2 commits into
p2-inc:mainfrom
Wictorgirardi:chore/wrap-up
Oct 5, 2026
Merged

pnzrr merged 2 commits into
p2-inc:mainfrom
Wictorgirardi:chore/wrap-up

Conversation

@Wictorgirardi

@Wictorgirardi Wictorgirardi commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Merge this last. It builds on #28, whose commit the branch includes, and adds repo-wide files for every example PR (#44, #45 and #46). Review the last two commits.

Summary

  • Dependabot: .github/dependabot.yml now covers every example. Add shared CI workflows, local Keycloak and contributing guide #28 only set it up for GitHub Actions and the shared Keycloak.
    • npm: one entry lists 10 projects. Separate entries hold back a major version for three of them:
      • Next.js: ESLint, because eslint-config-next's eslint-plugin-react doesn't support ESLint 10;
      • React Router: react-router and @react-router/*, because the Vercel preset supports only React Router 7;
      • multitenant: ESLint, @eslint/js and Vitest, because Nx's plugins cap them.
    • All npm entries skip TypeScript and @types/node majors and wait 7 days after a release.
    • pip: Django stays on 5.2 LTS, the newest version mozilla-django-oidc supports.
    • gradle covers both Spring Boot examples. docker-compose covers the shared Keycloak and both Spring compose files.
    • Updates run monthly, and minor and patch updates are grouped.
  • README: a build status table with each example's workflow badge.
  • keycloak/README.md: notes that the SAML example's Keycloak also uses port 8080, so the shared one has to be stopped first.

Test plan

  • .github/dependabot.yml validates against the SchemaStore schema.
  • Every badge points to a workflow file that its example PR adds.
  • After merge, Insights > Dependency graph > Dependabot lists every directory without errors.

Merge order and follow-ups

  1. Add shared CI workflows, local Keycloak and contributing guide #28: shared workflows, local Keycloak, e2e smoke test.
  2. Migrate the SPA examples: React, Vue, Nuxt, Angular and multitenant #44 (SPA examples), Migrate the server-side examples: Next.js, SvelteKit, React Router and Django #45 (server-side examples) and Migrate the Spring Boot examples: resource server with Angular, and SAML #46 (Spring Boot examples), in any order. Each one only touches its own examples' folders and workflows.
  3. This PR.

Outside the code:

  • Vercel env changes: Next.js, SvelteKit and React Router need them, all in Migrate the server-side examples: Next.js, SvelteKit, React Router and Django #45. The exact variables are in its description.
  • Vercel deploys: they don't run on PRs from forks, so the first deploys happen on the merges. Check that VERCEL_DEPLOYMENT_TOKEN and the project ID secrets are still valid.
  • Hosted realm: a Phase Two admin needs to fix the hosted p2examples realm login, which rejects every valid login with "Unexpected error when handling authentication request to identity provider". Until then, the live demos can't log in, although the local Keycloak works.

Shared templates (all tutorials)

  • templates/blog/_phase_two_starter_instructions.mdx (imported by 11 posts): still says "free Phase Two Starter instance… Create a Shared Deployment". Free shared realms were shut down on 2026-07-30.
  • templates/blog/_oidc_client_creation*.mdx:
    • add "Valid post logout redirect URIs: +", since every example now logs out through Keycloak;
    • turn off "Direct access grants" for public SPA clients;
    • mention per-example ports (Angular 4200, Django 8000, multitenant 4200/4201);
    • mention the local Keycloak in keycloak/ of the examples repo as an alternative.

React (oidc-client-ts): #44

  • blog/2023-08-02-secure-reactjs.mdx (L60–99):
    • npm install / npm start → pnpm install / pnpm dev;
    • the src/index.tsx snippet is now src/main.tsx and reads VITE_OIDC_ISSUER_URI / VITE_OIDC_CLIENT_ID from .env;
    • the redirect URI is the app origin, not …/authenticated;
    • logout uses signoutRedirect();
    • it still hardcodes the retired euc1.auth.ac host.
  • docs/securing-applications/react.md: documents @react-keycloak/web + keycloak-js, which no example uses. Rewrite around react-oidc-context or oidc-spa.

React (oidc-spa) and the tutorial starter: #44

  • blog/2024-10-10-oidc-spa.mdx (L57–222). It shows the oidc-spa v5 API, and npm install oidc-spa now installs v10, so the post fails as written. Update it:
    • createReactOidc({ issuerUri, clientId, publicUrl }) → src/oidc.ts with oidcSpa.withExpectedDecodedIdTokenShape(…).createUtils(), the oidcSpa() Vite plugin and <OidcInitializationGate>;
    • oidcTokens.decodedIdToken → decodedIdToken;
    • logout({ redirectTo: "current page" }) → logout({ redirectTo: "home" });
    • the synchronous getOidc().getTokens() → await getAccessToken() or fetchWithAuth;
    • the starter steps now match frameworks/reactjs/oidc-spa-starter/README.md;
    • line 28 still says "free instance".

Vue (oidc-client-ts): #44

  • blog/2023-09-14-secure-vue.mdx and templates/frameworks/_vuejs.mdx (L5–88):
    • the post points at a /nuxt/oidc-client-ts folder;
    • the hardcoded config object → .env;
    • client_secret in the browser → removed (public client with PKCE);
    • app.config.globalProperties.$auth and the Options API → useAuth() and <script setup>;
    • renewToken() → signinSilentCallback();
    • the router guard redirecting to /unauthenticated → removed;
    • files renamed: Header.vue → AppHeader.vue, Links.vue → AppFooter.vue, User.vue → UserStatus.vue, Token.vue → TokenPanels.vue.

Nuxt (keycloak-js, oidc-client-ts): #44

  • blog/2023-09-08-secure-nuxt.mdx and docs/securing-applications/nuxt.md. All paths move under app/ (Nuxt 4).
    • keycloak-js:
      • hardcoded euc1.auth.ac config → runtimeConfig.public (NUXT_PUBLIC_KEYCLOAK_*);
      • nuxtApp.$keycloak = → provide;
      • awaited init with silentCheckSsoRedirectUri, PKCE and token refresh;
      • composables/keycloak-c.ts → app/composables/useKeycloak.ts.
    • oidc-client-ts:
      • services/auth-service.ts with client_secret → app/plugins/oidc.client.ts, no secret;
      • stores/auth/index.ts → app/stores/auth.ts (Pinia 4);
      • useServices() → useAuthStore();
      • pages/logout.vue removed;
      • KEYCLOAK_* env vars → NUXT_PUBLIC_OIDC_*.

Angular: #44

  • blog/2024-08-01-secure-angular.mdx and templates/frameworks/_angular.mdx (L9–93):
    • authCodeFlowConfig (/index.html redirect, offline_access, debug output) → src/app/auth/auth.config.ts plus environment files;
    • constructor setup → provideAppInitializer and AuthService (signals);
    • *ngIf → @if;
    • user.component.ts → user-status/user-status.ts;
    • step numbering skips (4 → 6 → 10), and the post references a nonexistent UserActivation.component.ts.

Next.js: #45

  • blog/2023-08-14-secure-nextjs.mdx (L63–111) and docs/securing-applications/next.md (L10–58):
    • src/lib/auth.ts (hardcoded reg-example-1) → env-based src/auth.ts with token refresh, a claims-only session and Keycloak logout;
    • the route handler is NextAuth(authOptions);
    • remove the stray AuthProvider {...oidcConfig} React snippet and the SessionProvider snippet;
    • env table: NEXTAUTH_SECRET is a random value, not the client secret;
    • Next 13 → 16, npm → pnpm.

SvelteKit: #45

  • blog/2024-04-29-secure-sveltekit.mdx and templates/frameworks/_sveltekit.mdx (L9–84):
    • SvelteKitAuth({ secret, providers: [Keycloak(kcConfig)] }) → providers: [Keycloak], with AUTH_KEYCLOAK_* read automatically;
    • new jwt / session / events callbacks;
    • event.locals.getSession() → event.locals.auth();
    • export let data → $props();
    • client signIn / signOut → form actions;
    • remove the hardcoded 64-hex secret and the usw2.auth.ac / shared-deployment-001 values.

React Router v7 (formerly Remix): #45

  • blog/2024-04-24-secure-remix.mdx and templates/frameworks/_remix.mdx (L1–50):
    • retitle for React Router v7;
    • remix-keycloak's KeycloakStrategy → OAuth2Strategy.discover(issuer, …) from remix-auth-oauth2;
    • new Authenticator(sessionStorage) / isAuthenticated / logout → new Authenticator() plus a cookie session;
    • env: KEYCLOAK_ISSUER_DOMAIN + KEYCLOAK_REALM → KEYCLOAK_ISSUER, plus SESSION_SECRET;
    • GET /auth/signout → POST /logout with Keycloak end-session;
    • npm run dev -- --port 3000 → pnpm dev.

Django: #45

  • blog/2023-08-31-secure-django.mdx and docs/securing-applications/django.md:
    • quick start needs cp .env.example .env and a venv step;
    • the settings snippet uses env vars, with endpoints derived from OIDC_ISSUER, plus OIDC_USE_PKCE, OIDC_STORE_ID_TOKEN, OIDC_OP_LOGOUT_URL_METHOD and OIDC_RP_SCOPES;
    • mozilla_django_oidc.decorators (@oidc_protected, @oidc_logout) and request.oidc_user do not exist in mozilla-django-oidc 5.0.2 → use login_required / LoginRequiredMixin and the oidc_logout view;
    • backend path fragalysis.auth… → locallibrary.auth.KeycloakOIDCAuthenticationBackend;
    • the backend snippet differs from locallibrary/auth.py;
    • client setup: http://localhost:8000/*, post logout +, no direct access grants.

Multi-tenancy with Organizations: #44

  • blog/2024-11-11-multi-tenancy-with-organizations.md:
    • L94–101: hosted-only setup with * redirect URIs → the local Keycloak (--profile orgs) comes preconfigured; clients use PKCE with http://localhost:4200/* or http://localhost:4201/*;
    • L102 vs L104: "new york" vs "newyork" (the example uses newyork, display name "New York");
    • L110–112: "change the realm/client in code" → per-app .env / .env.local;
    • L116: orgs.png shows the old UI;
    • L74–82: the "User 1 / User 2" example contradicts the setup steps.

Spring Boot + Angular: #46

  • blog/2024-05-09-secure-spring-boot.mdx:
    • L38 / L81: Java 17 → 21 toolchain, Keycloak 24 → 26.6;
    • L40, L73–77: Spring Boot 3 → 4.1. Starters are now spring-boot-starter-security, spring-boot-starter-security-oauth2-resource-server and spring-boot-starter-webmvc, plus the *-test starters;
    • L52–61: the Initializr metadata lists an invalid package (com.example.spring-boot-keycloak), and the screenshot is outdated;
    • L83–104: the hosted starter no longer exists → the local compose file imports demo-realm with users test / test and noaccess / noaccess. The client is the public demo-spa (PKCE, http://localhost:4200/*, web origin and post-logout +), not the confidential client of _oidc_client_creation_client_auth.mdx. The non-admin user needs the realm role user;
    • L26 / L181: links to angular.io → angular.dev and Angular CLI 22.
  • templates/frameworks/_springboot.mdx:
    • L3: hosted Keycloak → local compose;
    • L9–19: the YAML now uses ${KEYCLOAK_ISSUER_URI:…}, drops jwk-set-uri, and adds app.cors.allowed-origins;
    • L32 / L105: the package path is src/main/java/com/example/springbootkeycloak;
    • L34–62: SecurityConfig has CORS, public /error and GET /api/test/anonymous, and anyRequest().denyAll(). @EnableWebSecurity and the constructor injection are gone;
    • L70–97: JwtClaimsConverter is no longer a @Component and has no unchecked cast;
    • L114–152: TestController uses @GetMapping, returns JSON records, and /anonymous is public (the post says both endpoints need a token, which was a bug);
    • L154–165: the password-grant curl no longer works (public client, direct grants off);
    • L186–237: NgModule / APP_INITIALIZER / HttpClientModule / localStorage / disablePKCE: true → standalone app.config.ts with provideOAuthClient, provideAppInitializer, PKCE and sessionStorage;
    • L241: npm run start → pnpm start;
    • L245–291: user.component with *ngIf and a guard that always returned of(true) → home with @if, API call buttons, and a functional authGuard on /protected.

SAML IdP-initiated SSO: #46

  • blog/2025-02-25-saml-idp-initiated-flow.mdx:
    • L96–103: the post recommends a Phase Two Starter cluster, but all its URLs are for a local Keycloak without /auth. Point it to the example's docker compose up -d --wait, which runs Keycloak on 8080 with test-realm imported. Hosted Phase Two URLs include /auth.
    • L145–151: creating an identity provider with the alias okta-broker clashes with the disabled placeholder the realm now contains. Readers edit it (entity ID, SSO URL, certificate, then enable it) or delete it first.
    • L153–155: readers run ./scripts/generate-sp-credentials.sh and start Keycloak before the SP. The SP serves its metadata at /saml2/metadata.
    • L157–169: "Import Client" pointed to saml-client.json, which is gone.
      • The client comes with the realm (keycloak/test-realm-export.json).
      • For another Keycloak, import the SP metadata from http://localhost:8081/saml2/metadata, which also turns "Client signature required" on, and set the IdP-initiated SSO URL name to okta-client.
    • L171–179: add the quick test without Okta: http://localhost:8080/realms/test-realm/protocol/saml/clients/okta-client, user test / test.
    • Optional, in "What Just Happened?":
      • the replay window of an unsolicited response is about a minute plus Spring's five minutes of clock skew, and the client's "Assertion Lifespan" shortens it;
      • restart the SP after recreating Keycloak, since the new container has new signing keys.
    • Still valid: the Okta SSO URL and Audience URI, okta-broker, okta-client, /login/saml2/sso, /saml2/metadata, the example link and the client screenshots.
    • Editorial:
      • the in-page links #service-provider-initated-flow and #identity-provider-initated-flow (L26–27) are misspelled;
      • typos: "differen" (L43), "Login in your Okta tenant" (L132), "turn of" (L232, L238), "a ACS", "a OIDC".

Outside the tutorials

  • The live demo links in the tutorials work again only once the hosted p2examples realm's login is fixed. Every valid login currently fails with "Unexpected error when handling authentication request to identity provider".

@pnzrr
pnzrr self-requested a review October 5, 2026 16:35
@pnzrr
pnzrr merged commit 204117a into p2-inc:main Oct 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants