Install
$ agentstack add skill-microsoft-power-platform-skills-setup-auth ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
> Plugin check: Run node "${PLUGIN_ROOT}/scripts/check-version.js" — if it outputs a message, show it to the user before proceeding.
Set Up Authentication & Authorization
Configure authentication (login/logout) and role-based authorization for a Power Pages code site. This skill supports multiple identity providers -- Microsoft Entra ID, Entra External ID (for customer-facing apps with self-service sign-up), OpenID Connect (generic), SAML2, WS-Federation, local authentication (username/password), Microsoft Account, Facebook, and Google. It also supports optional features including invitation-based registration and Terms & Conditions acceptance. Power Pages built-in 2FA is intentionally not scaffolded because the SendCode/VerifyCode pages are server-rendered and cannot be integrated into a SPA experience — use IdP-level MFA instead. It creates an auth service, type declarations, authorization utilities, auth UI components, and role-based access control patterns appropriate to the site's framework and chosen identity provider(s).
Core Principles
- Client-side auth is UX only — Power Pages authentication is server-side (session cookies). Client-side role checks control what users see, not what they can access. Server-side table permissions enforce actual security.
- Framework-appropriate patterns — Every auth artifact (hooks, composables, services, directives, guards) must match the detected framework's idioms and conventions.
- Development parity — Include mock data for local development so developers can test auth flows and role-based UI without deploying to Power Pages.
Initial request: $ARGUMENTS
> Prerequisites: > > - An existing Power Pages code site created via /create-site > - The site must be deployed at least once (.powerpages-site folder must exist) > - Web roles must be created via /create-webroles
Workflow
- Phase 1: Check Prerequisites — Verify site exists, detect framework, check web roles
- Phase 2: Plan — Gather auth requirements and present plan for approval
- Phase 3: Create Auth Service — Auth service with login/logout and type declarations
- Phase 4: Create Authorization Utils — Role-checking functions and wrapper components
- Phase 5: Create Auth UI — Login/logout button integrated into navigation
- Phase 6: Implement Role-Based UI — Apply role-based patterns to site components
- Phase 7: Verify Auth Setup — Validate all auth files exist, build succeeds, auth UI renders
- Phase 8: Review & Deploy — Summary and deployment prompt
Phase 1: Check Prerequisites
Goal: Confirm the project exists, identify the framework, verify deployment status and web roles, and check for existing auth code.
Actions
1.1 Locate Project
Look for powerpages.config.json in the current directory or immediate subdirectories:
**/powerpages.config.json
If not found: Tell the user to create a site first with /create-site.
1.2 Detect Framework
Read package.json to determine the framework (React, Vue, Angular, or Astro). See ${PLUGIN_ROOT}/references/framework-conventions.md for the full framework detection mapping.
1.3 Check Deployment Status
Look for the .powerpages-site folder:
**/.powerpages-site
If not found: Tell the user the site must be deployed first:
> "The .powerpages-site folder was not found. The site needs to be deployed at least once before authentication can be configured."
> 🚦 Gate (plan · setup-auth:1.3.deploy-first): .powerpages-site missing — auth setup writes site settings inside that folder. Deploy first or stop. > > Trigger: Phase 1.3 detected no .powerpages-site folder. > Why we ask: Auto-deploy picks the wrong env; skipping leaves auth wiring broken. > Cancel leaves: Nothing — no auth files written yet.
Use AskUserQuestion:
| Question | Options | |----------|---------| | Your site needs to be deployed first. Would you like to deploy now? | Yes, deploy now (Recommended), No, I'll do it later |
If "Yes, deploy now": Invoke /deploy-site, then resume.
If "No": Stop — the site must be deployed first.
1.4 Check Web Roles
Look for web role YAML files in .powerpages-site/web-roles/:
**/.powerpages-site/web-roles/*.yml
Read each file and compile a list of existing web roles (name, id, flags).
> 🚦 Gate (plan · setup-auth:1.4.create-webroles): No web roles found — role-based authorization needs at least one role. Create roles first or skip and add later. > > Trigger: Phase 1.4 found no YAML files in .powerpages-site/web-roles/. > Why we ask: Auto-invoking /create-webroles runs another full skill; auto-skipping leaves RBAC checks against an empty role set. > Cancel leaves: Nothing — no auth files written yet.
If no web roles exist: Warn the user that web roles are needed for authorization. Ask via AskUserQuestion whether to create them first:
| Question | Options | |----------|---------| | No web roles were found. Web roles are required for role-based authorization. Would you like to create them now? | Yes, create web roles first (Recommended), Skip — I'll add roles later |
If "Yes": Invoke /create-webroles, then resume.
If "Skip": Continue — auth service and login/logout will still work, but role-based authorization will need roles created later.
1.5 Discover Existing Auth Configuration
Always run this discovery step, even on a first invocation — the site may have site settings from a prior run, or from hand-editing the YAML files, even if no SPA auth code exists yet. The goal is to make sure we never silently drop a provider that's already configured server-side.
Step 1 — Scan .powerpages-site/site-settings/ for already-configured providers.
Detect existing providers by matching site-setting filenames against these patterns:
| Pattern | Maps to provider type | |---|---| | Authentication-OpenIdConnect-{Name}-AuthenticationType.sitesetting.yml | OIDC (Entra External ID, Okta, Auth0, generic OIDC, B2C — all share the OIDC path) | | Authentication-SAML2-{Name}-AuthenticationType.sitesetting.yml | SAML2 | | Authentication-WsFederation-{Name}-AuthenticationType.sitesetting.yml | WS-Federation | | Authentication-OpenAuth-{Microsoft\|Facebook\|Google}-{ClientId\|AppId}.sitesetting.yml | Social OAuth | | Authentication-Registration-LocalLoginEnabled.sitesetting.yml with value true | Local Authentication |
For each detected provider, read its full set of .sitesetting.yml files to extract: Authority / MetadataAddress, ClientId / AppId, AuthenticationType (the providerIdentifier), Caption or display name (if present), and the {Name} slug used in the keys (e.g., OpenIdConnect_1, EntraExternalId).
Distinguishing Entra ID variants from OIDC — by Authority URL pattern:
| Authority pattern | Provider type | Notes | |---|---|---| | https://login.windows.net/{guid}/ (no /v2.0/) — site's parent tenant | Microsoft Entra ID (workforce) — type: 'entra-id' | Auto-populated by Power Pages on site creation. The {Name} slug is usually AzureAD. Set providerIdentifier to undefined in AUTH_PROVIDERS — runtime resolver derives it from Portal.tenant. | | https://{subdomain}.ciamlogin.com/{tenantId} (no trailing /v2.0/) | Entra External ID — type: 'oidc' | Customer tenant. Must include explicit providerIdentifier matching the Authority. | | https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/v2.0/{policy} | Azure AD B2C (legacy) — type: 'oidc' | Older B2C product. Must include explicit providerIdentifier. | | Any other OIDC authority (Okta, Auth0, Ping, etc.) | OIDC (Generic) — type: 'oidc' | Must include explicit providerIdentifier. |
The Entra ID (workforce) case is special — when Phase 1.5 discovery detects Authentication/OpenIdConnect/AzureAD/* settings on the site (which Power Pages auto-creates for the parent tenant), add a single entry to EXISTING_PROVIDERS:
{
id: 'entra-id',
type: 'entra-id',
displayName: existingCaption || 'Sign in with Microsoft',
// NO providerIdentifier — resolveProviderIdentifier() derives it from Portal.tenant
}
Do NOT extract the tenant ID from the existing Authority site setting just to hardcode it back into AUTH_PROVIDERS — the runtime resolver handles it. This keeps the SPA code portable if the site is ever cloned to a different tenant.
Step 2 — Scan for existing SPA auth code.
Check for these files and read their key markers:
src/services/authService.tsor.js— look forAUTH_PROVIDERSarray (current pattern) vs singleAUTH_PROVIDERconstant (legacy)src/types/powerPages.d.ts— exists or notsrc/utils/authorization.ts— exists or not- Auth components (
AuthButton.*,Login.*,Registration.*,RedeemInvitation.*, etc.) — list which exist src/pages/Login.tsx— extract which providers it currently renders (viaAUTH_PROVIDERSimport or inline)
Step 3 — Present findings to the user.
If providers were detected from site settings, present them with their config:
I found these existing auth providers on your site:
✓ Entra External ID
- ProviderName: OpenIdConnect_1
- Tenant: ba275000-98c8-404d-a6f0-c5450f2aa668
- ClientId: e728d63e-1190-495a-ae29-663e9cc10877
- Configured in site settings: yes
- Surfaced in SPA UI: NO (authService.ts has no entry for this provider)
✓ Local Authentication
- LoginByEmail: true
- Surfaced in SPA UI: yes
Use AskUserQuestion:
| Question | Header | Options | |----------|--------|---------| | I found existing auth providers on your site. What would you like to do? | Existing auth | Keep all existing providers and add a new one (Recommended) — preserves what's there, adds what you ask for next, Keep all existing providers (no new provider this run) — re-generates SPA code to surface what's already in site settings, Replace everything with a new configuration — wipes existing site settings and SPA code, starts fresh |
"Keep all existing providers and add a new one" (default path):
- Store the discovered providers as
EXISTING_PROVIDERS— these will be merged into theAUTH_PROVIDERSarray generated in Phase 3.2 - Phase 2.1 will prompt for the NEW provider being added; the existing ones are kept untouched
- For local auth specifically — if
Local Authenticationis inEXISTING_PROVIDERS, always regenerate the local auth SPA code (login flow, registration page, forgot/reset password, redeem invitation) from the user's Phase 2.1 answers. Don't try to preserve hand-edited local-auth code — the local flows are complex enough that partial updates introduce more bugs than they avoid.
"Keep all existing providers (no new provider this run)":
- Skip the Phase 2.1 provider selection question entirely
- Re-derive
AUTH_PROVIDERSfromEXISTING_PROVIDERSonly - Useful for: fixing a site where the SPA UI is missing a provider that's already in site settings (the exact bug this branch was created to fix)
"Replace everything with a new configuration":
- Set
EXISTING_PROVIDERS = [] - Delete existing OIDC/SAML2/WsFed/OpenAuth site-setting YAMLs as part of Phase 8.1
- Run Phase 2.1 as if no providers existed
> DO NOT offer a "skip / no changes" option. If the user invokes setup-auth, they want auth set up — silently doing nothing is worse than asking.
Output
- Project root path confirmed
- Framework identified (React, Vue, Angular, or Astro)
- Deployment status verified
- Web roles inventory compiled
EXISTING_PROVIDERSlist compiled from site settings, with provider type, ProviderName slug, ClientId/Authority/etc. for eachMERGE_MODEchosen:keep-and-add(default) |keep-only|replace-all- SPA auth file inventory recorded (which files exist, whether they use
AUTH_PROVIDERSarray or legacy single-provider pattern)
Phase 2: Plan
Goal: Gather authentication requirements from the user and present the implementation plan for approval.
Actions
2.0 Smart Auth Inference (Before Asking)
Before asking the user which providers they want, analyze the site context from Phase 1 (site name, purpose, audience type) and try to infer appropriate auth settings automatically:
Inference rules:
| Site Type | Inferred Auth Settings | Rationale | |-----------|----------------------|-----------| | Internal/employee portal (HR, dashboard, admin) | Entra ID + invitation-only registration (OpenRegistrationEnabled=false, InvitationEnabled=true) | Internal sites should restrict access to invited employees only | | Customer-facing portal (support, self-service) | Entra External ID + open registration | Customer portals need self-service sign-up for customers | | Partner portal (B2B, vendor) | Entra ID + invitation-only registration | Partners are pre-vetted; open registration is a security risk | | Public site with protected features (e-commerce, community) | Entra External ID + open registration + optional Google/Facebook | Public sites benefit from social login for frictionless sign-up | | Loan/financial/banking portal | Entra External ID + invitation-only registration | Financial sites require controlled access for compliance |
If you can infer with confidence, present the recommendation with rationale:
> "Based on your site purpose ({purpose}), I recommend: > - {provider} for authentication > - {registration mode} because {rationale} > > Would you like to proceed with this configuration, or choose different providers?"
| Question | Options | |----------|---------| | Would you like to proceed with this recommended configuration? | Yes, proceed with recommendation, No, let me choose providers |
If "Yes": Skip Phase 2.1 provider selection and proceed directly to collecting provider-specific details (ClientId, tenant name, etc.) for the recommended provider(s).
If "No" or if you cannot infer with confidence: Fall back to Phase 2.1 below.
2.1 Gather Requirements
> 🚦 Gate (plan · setup-auth:2.1.requirements): Pick which auth features to build (login+logout / RBAC / both). Covers the conditional follow-up "which roles get access" sub-prompt in the same step. > > Trigger: Phase 2.1 entry. > Why we ask: Wrong feature set gets generated — e.g. building RBAC files when the user only wanted login. > Cancel leaves: Nothing — no auth files written yet.
Re-run handling — when Phase 1.5 detected existing providers:
The behavior depends on the MERGE_MODE chosen in Phase 1.5:
keep-only(user chose "keep all existing, no new provider this run") → Skip the new-provider selection question entirely. Proceed to the "Local Authentication" follow-ups only if local was detected. Phase 3.2 will generateAUTH_PROVIDERSfromEXISTING_PROVIDERSonly.keep-and-add(default — user wants to add one more) → Ask the user what to add. The provider selection question below should still be multi-select (the user could be adding multiple new providers in one go), but the existing providers are NOT in the list (they're already configured — the question is asking what's new). Common patterns:- User has Entra External ID, wants to add Local Auth → user selects "Local Authentication" → ask local follow-ups → Phase 3.2 merges
- User has Entra External ID + Local, wants to add a second Entra External ID tenant → user selects "Entra External ID" → after collecting Authority/ClientId, ask:
"You already have an Entra External ID provider configured for tenant {existing-tenant}. This new one is a separate instance — give it a distinct ProviderName slug (used in site setting keys like Authentication/OpenIdConnect/{ProviderName}/* and in code as the provider id)."Let the user pick a slug (default to the next incrementing number, e.g.,OpenIdConnect_2) or pick
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: microsoft
- Source: microsoft/power-platform-skills
- License: MIT
- Homepage: https://aka.ms/ppskills
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.