- Guides & Tutorials
- Register a Microsoft Graph Application
Register a Microsoft Graph Application
The Teams meeting pipeline reads meeting transcripts, recordings, and related artifacts from Microsoft Graph usingapp-only(daemon) authentication — no user sign-in, no interactive consent per meeting. That requires an Azure AD application registration with admin-consented application permissions.
This guide walks through:
- Creating the app registration
- Creating a client secret
- Granting the Graph API permissions the pipeline needs
- Admin-consenting those permissions
- (Optional) Scoping the app to specific users with an Application Access Policy
You needtenant admin rights(or an admin to grant consent on your behalf) to finish this. Bookmark the values you collect — they go into~/.hermes/.envat the end.
~/.hermes/.env
Prerequisites
- A Microsoft 365 tenant with Teams Premium or Teams licenses that produce meeting transcripts and recordings
- Admin access to the Azure portal atentra.microsoft.com
- A publicly reachable HTTPS endpoint for Graph change notifications (set up later, in the webhook listener step)
Step 1: Create the App Registration
- Sign in toentra.microsoft.comas a tenant admin.
- Navigate toIdentity → Applications → App registrations.
- ClickNew registration.
- Fill in:Name:Hermes Teams Meeting Pipeline(or any name you’ll recognize).Supported account types:Accounts in this organizational directory only (Single tenant).Redirect URI:leave blank — app-only auth does not need one.
- ClickRegister.
- Name:Hermes Teams Meeting Pipeline(or any name you’ll recognize).
- Supported account types:Accounts in this organizational directory only (Single tenant).
- Redirect URI:leave blank — app-only auth does not need one.
Hermes Teams Meeting Pipeline
You’ll land on the app’s overview page. Copy two values:
- Application (client) ID→MSGRAPH_CLIENT_ID
- Directory (tenant) ID→MSGRAPH_TENANT_ID
MSGRAPH_CLIENT_ID
MSGRAPH_TENANT_ID
Step 2: Create a Client Secret
- In the left nav, openCertificates & secrets.
- ClickNew client secret.
- Description:hermes-graph-secret.Expires:pick a value that matches your rotation policy (6-24 months is typical).
- ClickAdd.
- Copy theValuecolumn immediately — it’s only shown once. That value isMSGRAPH_CLIENT_SECRET.
hermes-graph-secret
MSGRAPH_CLIENT_SECRET
TheSecret IDcolumn is not the secret. You want theValuecolumn.
TheSecret IDcolumn is not the secret. You want theValuecolumn.
Step 3: Grant Graph API Permissions
The pipeline uses a minimum-viable set of application permissions. Add only what you need; each one widens what the app can read tenant-wide.
- In the left nav, openAPI permissions.
- ClickAdd a permission→Microsoft Graph→Application permissions.
- Add the permissions from the table below that match what you want the pipeline to do.
- After adding, clickGrant admin consent for
. The Status column should flip to a green checkmark for every permission.
<your tenant>
Required for transcript-first summaries
| Permission | What it lets the app do |
|---|---|
| OnlineMeetings.Read.All | Read Teams online meeting metadata (subject, participants, join URL). |
| OnlineMeetingTranscript.Read.All | Read meeting transcripts generated by Teams. |
OnlineMeetings.Read.All
OnlineMeetingTranscript.Read.All
Required for recording fallback (when a transcript is unavailable)
| Permission | What it lets the app do |
|---|---|
| OnlineMeetingRecording.Read.All | Download Teams meeting recordings for offline STT processing. |
| CallRecords.Read.All | Resolve meetings from call records when only the join URL is known. |
OnlineMeetingRecording.Read.All
CallRecords.Read.All
Required for outbound summary delivery (Graph mode only)
Ifplatforms.teams.extra.delivery_modeisgraph, the pipeline posts summaries into a Teams channel or chat via the Graph API. Skip these if you useincoming_webhookdelivery mode instead.
platforms.teams.extra.delivery_mode
graph
incoming_webhook
| Permission | What it lets the app do |
| — | — |
| ChannelMessage.Send | Post messages into Teams channels on behalf of the app. |
| Chat.ReadWrite.All | Post messages into 1:1 and group chats (only if you setchat_idas the delivery target). |
ChannelMessage.Send
Chat.ReadWrite.All
chat_id
Not recommended
- OnlineMeetings.ReadWrite.All/Chat.ReadWritewithout.All— broader than the pipeline needs.
- Delegated permissions — the pipeline uses app-only (client-credentials) flow; delegated permissions won’t work without user sign-in.
OnlineMeetings.ReadWrite.All
Chat.ReadWrite
.All
Step 4: (Recommended) Scope the App with an Application Access Policy
By default, application permissions likeOnlineMeetings.Read.Allgrant the app access toeverymeeting in the tenant. For partner demos and dev tenants that’s fine; for production you almost certainly want to restrict which users’ meetings the app can read.
OnlineMeetings.Read.All
Microsoft providesApplication Access Policiesfor Teams exactly for this. The policy is a PowerShell-only surface; there’s no portal UI for it.
From an admin PowerShell with the MicrosoftTeams module installed and connected (Connect-MicrosoftTeams):
Connect-MicrosoftTeams
# Create a policy scoped to the Hermes appNew-CsApplicationAccessPolicy ` -Identity "Hermes-Meeting-Pipeline-Policy" ` -AppIds "<MSGRAPH_CLIENT_ID>" ` -Description "Restrict Hermes meeting pipeline to allow-listed users"# Grant the policy to specific users whose meetings the pipeline may readGrant-CsApplicationAccessPolicy ` -PolicyName "Hermes-Meeting-Pipeline-Policy" ` -Identity "alice@example.com"Grant-CsApplicationAccessPolicy ` -PolicyName "Hermes-Meeting-Pipeline-Policy" ` -Identity "bob@example.com"
Propagation can take up to 30 minutes after granting. Verify with:
Test-CsApplicationAccessPolicy -Identity "alice@example.com" -AppId "<MSGRAPH_CLIENT_ID>"
Without the policy,anyuser’s meetings are readable — that’s what the permission technically grants. Don’t skip this step on a production tenant.
Step 5: Write the Credentials to Your Env File
Put the three values you collected into~/.hermes/.env:
~/.hermes/.env
MSGRAPH_TENANT_ID=<directory-tenant-id>MSGRAPH_CLIENT_ID=<application-client-id>MSGRAPH_CLIENT_SECRET=<client-secret-value>
Set file permissions so only you can read the secret:
chmod 600 ~/.hermes/.env
Step 6: Verify the Token Flow
Hermes ships a Graph auth smoke-test. From your Hermes install:
python -c "import asynciofrom tools.microsoft_graph_auth import MicrosoftGraphTokenProviderprovider = MicrosoftGraphTokenProvider.from_env()token = asyncio.run(provider.get_access_token())print('Token acquired, length:', len(token))print(provider.inspect_token_health())"
A successful run prints a long token string and a health dict showingcached: Trueand anexpires_in_secondsvalue near 3600. Failures produce aMicrosoftGraphTokenErrorwith the Azure error code — the most common are:
cached: True
expires_in_seconds
MicrosoftGraphTokenError
| Azure error | Meaning | Fix |
| — | — | — |
| AADSTS7000215: Invalid client secret | Secret value mismatched or expired. | Generate a new secret in step 2; update.env. |
| AADSTS700016: Application not found | WrongMSGRAPH_CLIENT_IDor wrong tenant. | Double-check the values from step 1 are from the same app. |
| AADSTS90002: Tenant not found | Typo inMSGRAPH_TENANT_ID. | Copy the Directory (tenant) ID from the app overview again. |
| insufficient_claimsat call time (not token time) | Token acquires but Graph returns 401/403. | You skipped step 3 admin-consent, or added permissions but haven’t re-consented. Revisit API permissions and clickGrant admin consentagain. |
AADSTS7000215: Invalid client secret
.env
AADSTS700016: Application not found
MSGRAPH_CLIENT_ID
AADSTS90002: Tenant not found
MSGRAPH_TENANT_ID
insufficient_claims
Rotating the Client Secret
Azure client secrets have a hard expiry. Before yours expires:
- Create a second client secret in step 2 without deleting the first one.
- UpdateMSGRAPH_CLIENT_SECRETin~/.hermes/.envwith the new value.
- Restart the gateway so the new secret is picked up:hermes gateway restart.
- Verify with the smoke test above.
- Delete the old secret from the Azure portal.
MSGRAPH_CLIENT_SECRET
~/.hermes/.env
hermes gateway restart
Next Steps
Once credentials verify cleanly, continue with:
- Webhook listener setup— stand up themsgraph_webhookgateway platform that receives Graph change notifications.
- Pipeline configuration— configure the Teams meeting pipeline runtime and operator CLI.
- Outbound delivery— wire summaries back into a Teams channel or chat.
msgraph_webhook
Those pages land alongside the PRs that add the corresponding runtime. This credentials setup is a standalone prerequisite and is safe to complete in advance.