Source code for: Angular SPA Authentication with Keycloak: No Backend Required
Stack: Angular 20, Keycloak 26, keycloak-angular 19, OAuth 2.0 PKCE, Docker Compose
.
├── docker-compose.yml # Keycloak 26 container
├── keycloak/
│ └── realm-export.json # Pre-configured realm (optional import)
└── angular-keycloak-app/
├── public/
│ └── silent-check-sso.html # Silent SSO iframe redirect target
└── src/
├── app/
│ ├── core/
│ │ ├── guards/
│ │ │ └── auth.guard.ts # Functional guard with RBAC
│ │ └── services/
│ │ └── auth.service.ts # Keycloak API wrapper
│ ├── pages/
│ │ ├── home/ # Public landing page
│ │ ├── dashboard/ # Authenticated users only
│ │ ├── admin/ # admin role required
│ │ └── unauthorized/ # Role check failure page
│ ├── shared/
│ │ └── navbar/ # Auth-aware navigation
│ ├── app.component.ts
│ ├── app.config.ts # provideKeycloak() bootstrap
│ ├── app.routes.ts # Protected route declarations
│ └── keycloak.config.ts # Keycloak provider factory
└── environments/
├── environment.ts # Dev: localhost:8080
└── environment.prod.ts # Prod: your Keycloak domain
docker compose up -dWait ~30 seconds for Keycloak to be ready, then open http://localhost:8080
Option A — Import the pre-configured realm:
- Log in to the Admin Console with
admin/admin - Click the realm dropdown → Create realm
- Toggle Resource file and upload
keycloak/realm-export.json - Click Create
Option B — Manual setup:
- Create realm:
angular-demo - Create public OpenID Connect client:
angular-app- Standard flow: On | Client authentication: Off
- Valid redirect URIs:
http://localhost:4200/* - Valid post logout redirect URIs:
http://localhost:4200/* - Web origins:
http://localhost:4200 - Advanced → PKCE method:
S256
- Create realm roles:
user,admin - Create users:
john.doe/password→ assign role:userjane.admin/password→ assign roles:user,admin
cd angular-keycloak-app
npm install
npm start| Username | Password | Roles | Can Access |
|---|---|---|---|
john.doe |
password |
user |
Home, Dashboard |
jane.admin |
password |
user, admin |
Home, Dashboard, Admin |
| Package | Version | Purpose |
|---|---|---|
@angular/core |
^20.0.0 | Angular framework |
keycloak-angular |
^19.0.1 | Angular Keycloak integration |
keycloak-js |
^26.1.0 | Keycloak JS adapter (OIDC) |
Check the keycloak-angular compatibility matrix for your Angular version.
- No backend auth layer: The Angular SPA authenticates directly with Keycloak using OAuth 2.0 Authorization Code Flow + PKCE.
- Token storage: Tokens are kept in JS memory (not localStorage). A page refresh triggers a silent SSO check via hidden iframe.
- Bearer token scope: The interceptor only attaches tokens to URLs matching the
apiConditionregex inkeycloak.config.ts. Update this regex to match your API URL. - Signal-based reactivity:
KEYCLOAK_EVENT_SIGNALdrives authentication state — no RxJS subscriptions needed in components.