-
Notifications
You must be signed in to change notification settings - Fork 1
Features
Long-form feature reference for the first public release. For a quick overview, see the README.
The portal unifies three normally separate planes into a single table:
- Microsoft Entra ID roles — directory-scoped (e.g. Global Reader) and Administrative-Unit-scoped roles.
-
Azure Resource roles — discovered from a tenant-root
asTarget()enumeration so the portal does not need to crawl every subscription you can see. Scopes shown beneath each role: management group, subscription, resource group, or specific resource. - PIM for Groups — both Member and Owner access types.
Select any combination across all three planes and submit them as a single bulk operation. Results stream back per role; partial successes are normal and visible.
Active roles can be selected and deactivated in bulk with optimistic UI updates. The "Select All" affordance on the active table selects only PIM-activated roles, leaving permanent assignments untouched.
Roles whose policy requires approval are surfaced inline with a Pending tag from the moment the request is submitted. The activity-details modal shows the request ID and status code so you can correlate with notifications from your approver workflow.
Switch between home, guest, and member directories without signing out. Your selection persists in sessionStorage for the tab session. Each directory has its own role and policy cache so toggling does not blow away cached data.
Every eligible role exposes the policy requirements that govern its activation:
| Requirement | What it means |
|---|---|
| Justification | A reason is mandatory at submit |
| Ticket | A ticket system + ID is mandatory at submit |
| MFA | The user must have a recent strong authentication |
| Auth context | The user must satisfy a Conditional Access auth context (claims challenge) |
| Approval | The activation request must be approved before it takes effect |
| Max duration | Hard cap applied to the requested duration |
The policy matrix is fetched once per tenant and cached for 30 minutes in memory. See Policy Awareness for what the portal does with each requirement.
When a role's policy requires a Conditional Access auth context (acrs claim), the portal:
- Detects the requirement from the role policy.
- Triggers an MSAL re-auth with the appropriate claims challenge.
- Threads the resulting claims into every subsequent token acquisition for the operation, so all Graph and ARM calls satisfy the requirement without prompting again.
401 responses with WWW-Authenticate: insufficient_claims (or a JSON-encoded claims body) are also detected at the API client layer and resolved through the same flow.
Named role sets persisted in browser-local IndexedDB. Per-profile pre-fills for justification, ticket, and duration. Optional tenant scoping for guest scenarios. JSON import / export to move profiles between browsers, devices, and teammates (tenant scoping preserved on import). See Activation Profiles.
Every active role shows time-remaining, ticking every 30 seconds. Colour-coded urgency (green → yellow → red) as expiry approaches. Hovering a row reveals the absolute expiry time.
- Typed toast notifications (success / warning / error / info) with optional descriptions.
- Persistent in-session notification panel with an unread badge.
- Activity-details modal: per-role outcome, status code, error message, submission time, scheduled start, duration, justification, ticket number used.
- Dark (default), Light, and High contrast.
- Until you pick one explicitly, the portal follows your OS light / dark preference.
- Theme choice is saved in
localStorage.
- Type-ahead filter on both the eligible and active tables, matching role name and scope.
- Quick-toggle pills for role types (Entra / Azure / Groups).
- Saveable named filters that pin to the filter bar for one-click reuse.
The Settings modal exposes feature flags persisted to localStorage:
- Enable / disable individual planes (Entra / Azure / Groups)
- Default activation duration
- Show already-active roles in the eligible table
- Tenant-scoped profiles
- UI toggles (theme switcher in header, show inactive policies, persisted section state)
The portal ships a Web App Manifest (Portal/manifest.json) with display: standalone, maskable 192 / 512 icons, a theme-color, and the apple-mobile-web-app-* meta tags Safari needs.
In practice that means:
- Desktop (Chrome / Edge) — click the Install app icon in the address bar, or browser menu → Install PIMActivation Portal. It launches in its own window with its own icon, no browser chrome.
- Android (Chrome) — menu → Install app / Add to Home screen.
- iOS / iPadOS (Safari) — Share sheet → Add to Home Screen. Tapping the home-screen icon launches the portal full-screen with the title "PIM".
There is no service worker, so the portal does not function offline — installing it is purely about an app-like launch and window chrome. You still need a network connection to talk to Microsoft Graph and ARM.
The Help dropdown in the header surfaces an in-app guide, FAQ, "how it works" overview, and a direct link to GitHub Issues.
-
Tokens —
sessionStorageonly; cleared when the tab closes. -
Roles — per-tenant role cache in
localStorage, refreshable on demand. - Policies — 30-minute in-memory cache.
- Profiles — IndexedDB; survives across browser sessions.
-
Feature flags —
localStorage; surfaced in the Settings modal.