Skip to main content

Discussion: Understanding TideCloak Authentication in Next.js

Conceptual insights, best practices, and deep-dive flows (with SVG diagrams) for TideCloak authentication in Next.js.


🧠 How it works (deep dive)​

Below are the end-to-end flows summarized from the sample repo and READMEs.

Example project structure (sample repo)​

tidecloak-client-nextJS/
β”œβ”€β”€ public/
β”‚ └── silent-check-sso.html
β”œβ”€β”€ lib/
β”‚ β”œβ”€β”€ db.js
β”‚ β”œβ”€β”€ IAMService.js
β”‚ └── tideJWT.js
β”œβ”€β”€ pages/
β”‚ β”œβ”€β”€ index.js
β”‚ β”œβ”€β”€ fail.js
β”‚ β”œβ”€β”€ protected.js
β”‚ β”œβ”€β”€ api/
β”‚ | β”œβ”€β”€ retrieve.js
β”‚ | β”œβ”€β”€ store.js
β”‚ β”‚ └── endpoint.js
β”‚ └── auth/
β”‚ └── redirect.js
β”œβ”€β”€ middleware.js
β”œβ”€β”€ keycloak.json
β”œβ”€β”€ keys.json
└── package.json

Normal authorized access​

  1. User visits http://localhost:3000 and clicks Login.
  2. The app initializes a TideCloak session and redirects to TideCloak.
  3. TideCloak redirects the user to Tide (IdP).
  4. User completes sign-up/sign-in in Tide’s secure enclave.
  5. Tide issues tokens (with anonymity and role context).
  6. redirect.js exchanges the auth code for tokens and redirects for backend validation.
  7. middleware.js verifies tokens/roles, then continues to the protected destination.
  8. protected.js renders for the authenticated, authorized user.

Authorized flow

Automatic session restart (SSO)​

  1. Home page loads.
  2. Hidden silent-check-sso.html performs a background SSO check.
  3. If already signed in, TideCloak returns the code.
  4. App initializes tokens and redirects to validation.
  5. middleware.js re-validates tokens/roles.
  6. User lands on protected content without re-auth.

Automatic authorised access flow

Unauthenticated attempt​

  • Failed authentication brings the user back to the home page (index.js).

Unauthenticated access attempt flow

Unauthenticated flow

Unauthorized attempt​

  • Authenticated but insufficient roles β†’ redirect to fail.js (with sign-out option).

Unauthorized access attempt flow

Authorized API access​

  • From a protected page (e.g., protected.js), API requests include the bearer token.
  • Backend verifies with verifyTideCloakToken before returning secure data.

Authorized API access flow

Single-Sign-Out​

  • User-initiated SSO logout ends sessions across related clients.

Single-Sign-Out flow

Automated session refresh​

  • Background process keeps sessions alive with silent token refresh.

Automated refresh access flow

E2EE - Authorized decryption​

  1. Protected page loads a form (e.g. dob.js).
  2. Frontend requests the encrypted DoB from /api/retrieve with the bearer token.
  3. Backend verifies _tide_dob.selfdecrypt and fetches ciphertext (no server-held keys).
  4. Encrypted field is returned to the browser.
  5. Browser invokes Tide Fabric nodes; each validates access and contributes a partial.
  6. Responses are combined client-side to decrypt only for the authorized user.

Authorized decryption flow

E2EE - Authorized encryption​

  1. User edits a protected field (e.g., DoB).
  2. Browser engages Fabric nodes; each validates access and contributes to encryption.
  3. The encrypted value is posted to the backend.
  4. Backend validates and stores ciphertext (no decryption key at rest).

Authorized encryption flow


πŸ”‘ Why use TideCloak?​

TideCloak simplifies secure authentication by:

  • Handling OAuth2/OIDC and JWT verification reliably (including Edge middleware).
  • Providing built-in encryption/decryption helpers for sensitive fields (tag-based E2EE).
  • Supporting role-based access control (RBAC) at realm and client levels.
  • Integrating smoothly with both App Router and Pages Router in Next.js.

🧩 When should you use Middleware vs Client-side Authentication?​

Middleware (Edge)​

Use middleware when you need:

  • Global route protection (pages and APIs) before rendering.
  • Immediate redirection for unauthenticated/unauthorized users.
  • Centralized role checks per path pattern.

Client-side​

Use client-side auth when you need:

  • Conditional rendering of components (e.g., login/logout buttons, protected widgets).
  • UX logic that depends on authenticated state without hard blocking a route.
  • Quick reads from tokens (getValueFromToken, getValueFromIdToken) for UI.

Best practice: Use both - middleware to harden routes, client-side to refine UI.


πŸ› οΈ Best practices for redirect URIs​

  • Ensure the redirect route exists in your app.
  • Default is "/auth/redirect" if you don’t set one explicitly.
  • If you customize it in <TideCloakProvider config={{ redirectUri }}>, keep it consistent across environments to avoid broken flows.

πŸ“¦ How are roles managed in TideCloak?​

TideCloak roles live at two levels:

  • Realm roles - global to the TideCloak realm (e.g., "admin").
  • Client roles - scoped to a specific client/app (e.g., "editor").

They’re embedded in JWTs and can be checked with:

  • hasRealmRole('admin')
  • hasClientRole('editor', 'myclient') (client is optional; defaults to your app client)

🚨 Common Pitfalls​

  • Missing "/auth/redirect" page when relying on the default route.
  • Encrypting objects instead of strings/Uint8Array with doEncrypt() (will fail).
  • Middleware matcher too broad/too narrow - be precise for public vs protected routes.
  • Missing _tide_<tag>.selfencrypt / _tide_<tag>.selfdecrypt roles for E2EE.