Skip to content
Report library
Purpose / Other

Entra App Registration Skill Security Audit

What the author says it does (original text)

Guides Microsoft Entra ID app registration, OAuth 2.0 authentication, and MSAL integration. USE FOR: create app registration, register Azure AD app, configure OAuth, set up authentication, add API permissions, generate service principal, MSAL example, console app auth, Entra ID setup, Azure AD authentication. DO NOT USE FOR: Key Vault secrets (use azure-keyvault-expiration-audit), general Azure re

Independent security check

Do not install or run it yet

Files checked
17
Risks found
6
Could it run dangerous commands?Looks for programs run straight after downloading, remote control of your computer, and hidden commands.No risks found
Could it expose your files or keys?Looks for uploads of files containing passwords or keys, and keys written directly in the code.Risks found: 1
Medium risk

Troubleshooting asks the user to paste a live access token into a website

Source references: 2
What we found

The guide instructs the user to copy an access token and paste it into `jwt.ms`. An access token is a bearer credential, so submitting the complete value exposes it to the page and its execution environment. Calling the site “secure” does not remove that exposure surface.

Why this matters

If the domain, browser extensions, proxy, logging path, or current session is compromised, the token could be replayed before expiration to access data allowed by its `scp` or `roles` claims.

The troubleshooting guide actively tells users to copy a complete access token and paste it into an external webpage. Even if the named service is intended for decoding, the page and its scripts receive the bearer credential; disclosure of a still-valid token could permit API calls within its permissions. Users can request a local offline decoder, or at minimum use a short-lived, low-privilege non-production token and revoke the session afterward.

references/troubleshooting.md:175In the instructionsOpen original file
## Token IssuesUnless the the access token is encrypted, you can decode and view its claims securely at https://jwt.ms. **Don't** use any other website to decode an access token. Compare the claims in the token with the app registration's configuration to identify issues.
Show 1 other places
references/troubleshooting.md:181In the instructionsOpen original file
### JWT Token Decoder**Tool:** https://jwt.ms**How to use:**1. Copy your access token2. Paste into jwt.ms3. Review claims:   - `aud` - Audience (should match your API)   - `iss` - Issuer (should be login.microsoftonline.com)   - `scp` - Delegated permissions   - `roles` - Application permissions   - `exp` - Expiration timestamp   - `oid` - User object ID
Could it delete files or keep running?Looks for broad file deletion, disk overwrites, and programs set to start automatically.Risks found: 2
High risk

The command for generating a client secret deletes existing credentials and can stop services

Source references: 2
What we found

The guide uses `az ad app credential reset` to create a secret and explicitly warns that resetting deletes all existing credentials. Other application instances or deployments may still depend on those secrets or certificates.

Why this matters

Production services, automation, or integrations using an old credential may immediately lose authentication. Recovery can take substantial time if no alternative credential remains.

The guide presents `credential reset` as the way to create a secret and explicitly warns that resetting deletes all existing credentials. Running an example against an established production app could immediately break services that still use old secrets or certificates. The warning reduces accidental misuse but does not prevent it; users should inventory dependencies first and request a rotation procedure that preserves existing credentials.

references/cli-commands.md:134In the instructionsOpen original file
### Create client secret```bash# Create secret with default expirationaz ad app credential reset --id $APP_ID# Create secret with custom expirationaz ad app credential reset --id $APP_ID --years 1# Create secret with specific end dateaz ad app credential reset --id $APP_ID --end-date "2025-12-31"```**Save the output:**```json{  "appId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",  "password": "your-secret-value-SAVE-THIS",  "tenant": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}```**⚠️ Important:** Resetting Client credential will delete all existing credentials.**⚠️ Important:** The secret value is only shown once. Store it securely (e.g., Azure Key Vault).
Show 1 other places
references/cli-commands.md:156In the instructionsOpen original file
**⚠️ Important:** Resetting Client credential will delete all existing credentials.**⚠️ Important:** The secret value is only shown once. Store it securely (e.g., Azure Key Vault).
High risk

The cleanup script bulk-deletes matching Entra applications without per-item confirmation

Source references: 1
What we found

The script obtains every application ID whose display name matches `Test*` and passes each ID directly to `az ad app delete`. It does not show the tenant, owner, dependencies, or ask for confirmation per application.

Why this matters

A similarly named application registration and its associated service principal may be deleted while still in use, breaking sign-ins, API permissions, and service integrations.

This is explicitly a cleanup example, so deletion matches the section's purpose. However, when run it enumerates every app matching `Test*` and deletes each one directly, without checking tenant, owner, dependencies, or obtaining per-item confirmation. The display-name pattern may match active apps unintentionally. Users should first verify the tenant and full candidate list and request preview and explicit-confirmation safeguards.

references/cli-commands.md:399In the instructionsOpen original file
### Cleanup script```bash#!/bin/bash# Delete all apps matching patternaz ad app list --display-name "Test*" --query "[].appId" -o tsv | while read APP_ID; do  echo "Deleting app: $APP_ID"  az ad app delete --id $APP_IDdone```
Could it bypass safety checks?Looks for skipped website security checks, excessive file access, or actions that skip your approval.Risks found: 3
High risk

The Bicep template registers redirect addresses not confirmed to be user-controlled

Source references: 2
What we found

The template defaults web callbacks and SPA redirects to `myapp.azurewebsites.net`. OAuth responses are sent to registered redirect URIs, but the template does not require proof that the user controls this host before deployment.

Why this matters

If deployed unchanged while that host is controlled or later claimed by someone else, authorization codes or tokens could be delivered to that host, exposing sign-in sessions and authorized data.

If deployed without overriding its defaults, this IaC registers example-domain Web and SPA redirect addresses and passes them into the application resource. If the user does not control that domain, authentication responses could be directed to a third-party host. Users should require mandatory, default-free parameters and verify ownership of every production URI before deployment.

references/BICEP-EXAMPLE.bicep:18In the instructionsOpen original file
@description('Redirect URIs for web application')param webRedirectUris array = [  'https://localhost:5001/signin-oidc'  'https://myapp.azurewebsites.net/signin-oidc']@description('Redirect URIs for single-page application')param spaRedirectUris array = [  'http://localhost:3000'  'https://myapp.azurewebsites.net']
Show 1 other places
references/BICEP-EXAMPLE.bicep:48In the instructionsOpen original file
  // Web application settings  web: {    redirectUris: webRedirectUris    implicitGrantSettings: {      enableIdTokenIssuance: true      enableAccessTokenIssuance: false    }    homePageUrl: 'https://myapp.azurewebsites.net'    logoutUrl: 'https://myapp.azurewebsites.net/signout-oidc'  }  // Single-page application settings  spa: {    redirectUris: spaRedirectUris  }
High risk

The template requests tenant-wide user access and the guide offers blanket admin consent

Source references: 4
What we found

The Bicep template requests the `User.Read.All` application permission by default, alongside delegated mail and directory-related scopes. A separate command grants admin consent for all configured permissions. Application permissions operate without a signed-in user and always require admin consent.

Why this matters

If an administrator deploys the template and runs the consent command, the service principal can read full profiles for every user in the tenant without user interaction. Consenting users may also expose their mail. This exceeds what most basic sign-in applications require.

The template requests delegated permissions including Mail.Read and the User.Read.All application permission, which can read tenant-wide user profiles without user context. The guide separately provides an admin-consent command covering all configured permissions. If an administrator deploys the example and runs that command, the app gains access beyond basic sign-in. Users should require per-permission justification, approve only necessary access, and remove privileged defaults.

references/BICEP-EXAMPLE.bicep:121In the instructionsOpen original file
  // Required API permissions (Microsoft Graph)  requiredResourceAccess: [    {      // Microsoft Graph API      resourceAppId: '00000003-0000-0000-c000-000000000000'      resourceAccess: [        {          // User.Read - Delegated          id: 'e1fe6dd8-ba31-4d61-89e7-88639da4683d'          type: 'Scope'        }        {          // User.ReadBasic.All - Delegated          id: 'b340eb25-3456-403f-be2f-af7a0d370277'          type: 'Scope'        }        {          // Mail.Read - Delegated          id: '570282fd-fa5c-430d-a7fd-fc8dc98a9dca'          type: 'Scope'        }        {          // User.Read.All - Application          id: 'df021288-bdef-4463-88db-98f22de89214'          type: 'Role'        }      ]    }  ]
Show 3 other places
references/api-permissions.md:89In the instructionsOpen original file
### Common Application Permissions| Permission | What it allows | Admin Consent Required ||------------|---------------|----------------------|| `User.Read.All` | Read all users' full profiles | Yes (Always) || `User.ReadWrite.All` | Read and write all users' profiles | Yes (Always) || `Mail.Read` | Read mail in all mailboxes | Yes (Always) || `Mail.Send` | Send mail as any user | Yes (Always) || `Calendars.Read` | Read calendars in all mailboxes | Yes (Always) || `Directory.Read.All` | Read directory data | Yes (Always) || `Directory.ReadWrite.All` | Read and write directory data | Yes (Always) || `Group.ReadWrite.All` | Read and write all groups | Yes (Always) |
references/cli-commands.md:231In the instructionsOpen original file
### Grant admin consent```bash# Grant admin consent for all permissionsaz ad app permission admin-consent --id $APP_ID```**Note:** Admin consent is required for application permissions and some delegated permissions.
references/api-permissions.md:23In the instructionsOpen original file
### Application Permissions (App Context)**What:** Application acts with its own identity (no user)**When to use:**- Background services, daemons- Scheduled jobs- API-to-API calls without user**Examples:**- Read all users in organization- Send mail as any user- Access all SharePoint sites**Requirement:** Always requires admin consent
Medium risk

The console-app guidance enables both device-code and password flows

Source references: 1
What we found

The guide says “Allow public client flows” enables both device-code flow and resource-owner password flow, yet recommends turning it on for console applications generally. Needing device-code authentication does not mean an application should also be able to process user passwords directly.

Why this matters

If the application later implements or is induced to use the resource-owner password flow, user passwords enter the client processing path. That flow is incompatible or limited with MFA, Conditional Access, and modern passwordless authentication, increasing credential exposure.

The guide states that one setting enables both device-code and resource-owner-password flows, then broadly recommends enabling it for console apps. If an app only needs device-code or interactive authentication, this also permits a legacy flow that directly handles user passwords, increasing credential exposure and misuse risk. Users should require flow-specific configuration and confirmation that the resource-owner-password flow is disabled when unnecessary.

references/first-app-registration.md:95In the instructionsOpen original file
### Advanced Settings**Allow public client flows:**- **What it is:** Enables device code flow, resource owner password flow- **For console apps:** Turn this **ON**- **For web apps:** Keep **OFF**
Could it mislead the AI or hide text?Checks the skill instructions for requests to ignore you, influence the report, or hide text in invisible characters.No risks found
Could it change links or payment recipients without asking?Looks for forced referral or payment changes combined with instructions to hide the change.No risks found

Inside this skill

8 instruction sections

This Skill is an operational guide for Entra app registration, with portal steps, Azure CLI commands, and a Bicep template. Following them can create or modify applications, permissions, credentials, and service principals in the currently signed-in Azure tenant, rather than only producing local examples.

View source
SKILL.md:37In the instructionsOpen original file
### Step 1: Register the ApplicationCreate an app registration in the Azure portal or using Azure CLI.**Portal Method:**1. Navigate to Azure Portal → Microsoft Entra ID → App registrations2. Click "New registration"3. Provide name, supported account types, and redirect URI4. Click "Register"**CLI Method:** See [references/cli-commands.md](references/cli-commands.md)**IaC Method:** See [references/BICEP-EXAMPLE.bicep](references/BICEP-EXAMPLE.bicep)
references/cli-commands.md:257In the instructionsOpen original file
### Create service principal```bash# Create service principal for the appaz ad sp create --id $APP_ID```

The sample applications use MSAL to acquire a token, send it as a Bearer token to Microsoft Graph's `/me` endpoint, and print the user profile. This network access matches the stated authentication-example purpose.

View source
references/console-app-example.md:190In the instructionsOpen original file
def call_graph_api(access_token):    """Call Microsoft Graph API with access token"""    headers = {        'Authorization': f'Bearer {access_token}',        'Content-Type': 'application/json'    }        response = requests.get(        'https://graph.microsoft.com/v1.0/me',        headers=headers    )        if response.status_code == 200:        user_data = response.json()        print("\nUser profile from Microsoft Graph:")        print(json.dumps(user_data, indent=2))    else:

The documentation explicitly recommends least privilege, avoiding hardcoded secrets, and preferring managed identity in production. These are advisory safeguards and do not automatically constrain the permissions applied by later CLI commands or templates.

View source
SKILL.md:161In the instructionsOpen original file
|----------|---------------|| **Never hardcode secrets** | Use environment variables, Azure Key Vault, or managed identity || **Rotate secrets regularly** | Set expiration, automate rotation || **Use certificates over secrets** | More secure for production || **Least privilege permissions** | Request only required API permissions || **Enable MFA** | Require multi-factor authentication for users || **Use managed identity** | For Azure-hosted apps, avoid secrets entirely || **Validate tokens** | Always validate issuer, audience, expiration || **Use HTTPS only** | All redirect URIs must use HTTPS (except localhost) || **Monitor sign-ins** | Use Entra ID sign-in logs for anomaly detection |
Start here · InstructionsSKILL.md
entra-app-registration
Lines connect the instruction file to its sections, not an observed execution order. Select a section to read the source.

File reference map

References: 26
Files making referencesReferenced content
Lines show actual file references, not execution order. Select a node to highlight its connections and inspect the files and source locations. Dashed lines include files that still need locating.
Files and check records17 files

Coverage and gaps

Content covered in each file

These are the source ranges included in this check, not a guarantee that every issue has been resolved.

  • SKILL.mdFull text included
  • references/api-permissions.mdFull text included
  • references/BICEP-EXAMPLE.bicepFull text included
  • references/cli-commands.mdFull text included
  • references/console-app-example.mdFull text included
  • references/first-app-registration.mdFull text included
  • references/oauth-flows.mdFull text included
  • references/sdk/azure-identity-dotnet.mdFull text included
  • references/sdk/azure-identity-java.mdFull text included
  • references/sdk/azure-identity-py.mdFull text included
  • references/sdk/azure-identity-rust.mdFull text included
  • references/sdk/azure-identity-ts.mdFull text included
  • references/sdk/azure-keyvault-py.mdFull text included
  • references/sdk/azure-keyvault-secrets-ts.mdFull text included
  • references/sdk/microsoft-azure-webjobs-extensions-authentication-events-dotnet.mdFull text included
  • references/troubleshooting.mdFull text included
  • references/auth-best-practices.mdFull text included

This report is for the version above. We read the available code and instructions without running the skill or checking extra packages it installs. This is not a promise of safety: a different version or setup may behave differently.

  • SKILL.mdInstructions
  • references/BICEP-EXAMPLE.bicepSupporting file
  • references/api-permissions.mdSupporting file
  • references/auth-best-practices.mdSupporting file
  • references/cli-commands.mdSupporting file
  • references/console-app-example.mdSupporting file
  • references/first-app-registration.mdSupporting file
  • references/oauth-flows.mdSupporting file
  • references/sdk/azure-identity-dotnet.mdSupporting file
  • references/sdk/azure-identity-java.mdSupporting file
  • references/sdk/azure-identity-py.mdSupporting file
  • references/sdk/azure-identity-rust.mdSupporting file
  • references/sdk/azure-identity-ts.mdSupporting file
  • references/sdk/azure-keyvault-py.mdSupporting file
  • references/sdk/azure-keyvault-secrets-ts.mdSupporting file
  • references/sdk/microsoft-azure-webjobs-extensions-authentication-events-dotnet.mdSupporting file
  • references/troubleshooting.mdSupporting file

Operations mentioned in code and instructions

Connect to websites
SKILL.md:58In the instructionsOpen original file
- **SPAs**: Add redirect URIs, enable implicit grant flow if necessary- **Mobile/Desktop**: Use `http://localhost` or custom URI scheme- **Services**: No redirect URI needed for client credentials flow
SKILL.md:188In the instructionsOpen original file
- [Microsoft Identity Platform Documentation](https://learn.microsoft.com/entra/identity-platform/)- [OAuth 2.0 and OpenID Connect protocols](https://learn.microsoft.com/entra/identity-platform/v2-protocols)
SKILL.md:189In the instructionsOpen original file
- [Microsoft Identity Platform Documentation](https://learn.microsoft.com/entra/identity-platform/)- [OAuth 2.0 and OpenID Connect protocols](https://learn.microsoft.com/entra/identity-platform/v2-protocols)- [MSAL Documentation](https://learn.microsoft.com/entra/msal/)
Read keys or account settings
SKILL.md:59In the instructionsOpen original file
- **Mobile/Desktop**: Use `http://localhost` or custom URI scheme- **Services**: No redirect URI needed for client credentials flow
SKILL.md:73In the instructionsOpen original file
### Step 4: Create Client Credentials (if needed)
SKILL.md:129In the instructionsOpen original file
**Implementation:** Use Client Credentials flow (see [references/oauth-flows.md#client-credentials-flow](references/oauth-flows.md#client-credentials-flow))
Read files
SKILL.md:66In the instructionsOpen original file
**Common Microsoft Graph Permissions:**- `User.Read` - Read user profile- `User.ReadWrite.All` - Read and write all users
references/api-permissions.md:84In the instructionsOpen original file
| `Calendars.ReadWrite` | Read and write calendars | No || `Files.Read.All` | Read all files user can access | No || `Sites.Read.All` | Read items in all site collections | Yes |
references/api-permissions.md:216In the instructionsOpen original file
- User can: Only read their own profile- App granted: User.Read.All
Run commands
references/api-permissions.md:144In the instructionsOpen original file
```bash# List all Graph permissions (warning: long output)
references/api-permissions.md:174In the instructionsOpen original file
**CLI Method:**```bashaz ad app permission admin-consent --id $APP_ID
references/api-permissions.md:183In the instructionsOpen original file
**CLI:**```bashaz ad app permission list --id $APP_ID
Install extra software packages
references/console-app-example.md:128In the instructionsOpen original file
```bashpip install msal requests```
references/console-app-example.md:257In the instructionsOpen original file
npm init -ynpm install @azure/msal-node axios```
references/sdk/azure-identity-py.md:9In the instructionsOpen original file
```bashpip install azure-identity```
Lines read
2,795
File checksum (to compare versions)
891b19139d694dbbac241cf088d08f4d10ae6e5dbe86f4d9fff41db39fe39190