-
Notifications
You must be signed in to change notification settings - Fork 250
Certificate based connection for Teams
This script provides a controlled certificate-based connection workflow for Microsoft Teams PowerShell, with two mutually exclusive operating modes:
- Generate local certificate materials for app-based authentication.
- Use existing certificate credentials to connect to Microsoft Teams.
It can also optionally provision and configure Microsoft Entra ID app resources required for Teams certificate authentication.
The script enforces exactly one mode per run:
-GenerateLocalCertificate-UseCertificateAuth
If both or neither are supplied, execution stops with an error.
At startup, the script resolves paths relative to its own location (not the caller's current working directory):
-
GeneratedCertOutputPathdefaults to the parent directory of the script folder. -
CertificateMapPathresolution order:
- Parent folder
o365-tms-cert-auth.json - Script folder
o365-tms-cert-auth.json - If not found, default write path becomes parent folder
o365-tms-cert-auth.json
- Enforces TLS 1.2 minimum for outbound network calls.
- If
-enableLogis used, starts transcript logging too365-connect-teams.txtin the parent folder.
The script validates that the Microsoft Teams PowerShell module is available:
- Checks installation status.
- If missing, can prompt to install (unless
-nopromptis used). - Performs elevated install/update by relaunching the same PowerShell host executable with
RunAsand an encoded command payload. - Optionally checks/update against PSGallery (unless
-noupdateis used). - Imports module before mode-specific operations.
-
noprompt: Non-interactive preference; disables selection/input prompts. -
noupdate: Skips module version check/update. -
enableLog: Enables transcript logging.
GenerateLocalCertificateUseCertificateAuth
-
GeneratedCertSubject(defaultO365-TMS-AppAuth) -
GeneratedCertYearsValid(default2) GeneratedCertOutputPathExportGeneratedPfxGeneratedPfxPassword
TenantProfileNameOrganizationAppIdCertificateThumbprintCertificateMapPath
-
GraphResourceAppId(default Microsoft Graph app id) ProvisionEntraAppAppDisplayNameSetupClientId-
EntraDirectoryRoleName(defaultTeams Administrator) ValidateEntraOnConnectSkipEntraValidationOnConnectCopyDeviceCodeToClipboard
- Validates and creates output directory if needed.
- Creates a self-signed RSA 2048 / SHA-256 certificate in
Cert:\CurrentUser\My. - Sets certificate friendly name.
- Exports
.cerpublic certificate file. - Optionally exports
.pfxif-ExportGeneratedPfxis set:
- Uses
GeneratedPfxPasswordif provided. - Prompts for password if allowed and missing.
- Throws if password still unavailable.
- Outputs generated thumbprint and export paths.
When enabled, the script extends the generation flow to configure cloud prerequisites:
- Resolves/collects tenant identifier (
Tenantrequired in non-prompt mode). - Obtains delegated Graph token via device-code flow.
- Resolves Graph service principal and required app roles for Teams scenarios.
- Gets or creates app registration by display name.
- Uploads generated certificate as key credential if not already present.
- Ensures
requiredResourceAccessincludes expected Graph app roles. - Gets or creates service principal for the app.
- Assigns Graph app roles (admin consent path).
- Ensures Entra directory role assignment for the app service principal.
- Writes or updates a profile entry in the JSON profile map.
- Prints provisioning summary and a ready-to-run connect command.
Set-TeamsProfileMapEntry uses a named global mutex based on a hash of map path to guard concurrent writes:
- Waits up to 30 seconds for lock.
- Writes to temp file then atomically moves into target path.
- Replaces existing profile if app id or tenant/org match.
This design reduces profile corruption risk from simultaneous script runs.
Before connection, the script attempts to resolve missing values from profile map:
- Filters profile candidates by
ProfileName,Tenant, and/orOrganization. - If one match found, auto-selects.
- If multiple and prompts allowed, asks user to choose.
- If multiple and
-noprompt, throws and asks for explicit filters.
It then applies fallback behavior:
- Treats
Tenantas alias forOrganizationin cert-auth mode. - Validates required values are present: Organization/Tenant, AppId, CertificateThumbprint.
- Normalizes thumbprint (strip whitespace).
- Validates SHA-1 thumbprint format (40 hex chars).
- Verifies cert exists in
Cert:\CurrentUser\My. - Rejects expired cert.
- Warns when expiration is <= 30 days.
If -ValidateEntraOnConnect is enabled (and not overridden by -SkipEntraValidationOnConnect):
- Runs device-code Graph auth.
- Ensures app service principal exists.
- Ensures configured Entra directory role is assigned.
- Waits briefly for role propagation.
If this pre-check fails, script warns and continues to Teams connect attempt.
- Checks existing Teams online session if cmdlet is available.
- If existing session appears to target requested tenant/org, skips reconnect.
- Otherwise runs
Connect-MicrosoftTeamswith:
-TenantId-ApplicationId-CertificateThumbprint
- On success, prints connected tenant details and certificate/app details.
Executes elevated module management commands using encoded command text to avoid quoting/escaping issues through UAC boundary.
Loads and filters profile map entries from JSON and optionally prompts for profile selection if multiple matches remain.
Creates local self-signed cert and exports .cer and optional .pfx artifacts.
Runs OAuth 2.0 device code flow:
- Normalizes tenant input.
- Tries configured client id, then fallback public clients.
- Shows verification URI + user code (optionally clipboard copy).
- Polls token endpoint until success/timeout/decline.
- Returns access token.
Graph REST wrapper with retry/backoff for transient failures (429/5xx and throttling-like errors).
Ensures service principal exists for target app id.
Resolves Graph SP and required app-role ids used by provisioning.
Patches app registration requiredResourceAccess with missing Graph roles.
Assigns app roles to service principal with skip logic for already-granted roles.
Finds or activates directory role, then ensures membership for app service principal.
Concurrency-safe profile map update with lock, merge/replace logic, and atomic write strategy.
Gets or creates app registration and ensures certificate key credential exists.
Attempts tenant normalization or tenant-id resolution via OpenID metadata.
Builds signed client assertion JWT from local certificate and requests app-only Graph token.
Attempts to determine active tenant from Teams/Graph context and warns on mismatch with requested organization.
Prints local certificate details and, if possible, Entra app key-credential details for match verification.
- Script uses
try/catch/finallyat top level. - Fatal failures return exit code
1and print reason. - Success in generation/auth flows returns exit code
0where explicitexitis used. - If Teams connection was opened and an error occurs afterward, script attempts cleanup via
Disconnect-MicrosoftTeams. - Transcript is always stopped in
finallyif logging was enabled.
- Device code clipboard copy is opt-in (
CopyDeviceCodeToClipboard) due to shared-session leakage risk. - Uses certificate private key from local user store for client assertion signing.
- Elevated module install/update isolates command execution in a separate elevated process.
- Profile map includes sensitive operational metadata (tenant, app id, thumbprint); protect file access.
.\o365-connect-tms-cert.ps1 -GenerateLocalCertificate -GeneratedCertSubject "Contoso-TeamsAuth".\o365-connect-tms-cert.ps1 -GenerateLocalCertificate -ExportGeneratedPfx.\o365-connect-tms-cert.ps1 -GenerateLocalCertificate -ProvisionEntraApp -Tenant "contoso.onmicrosoft.com".\o365-connect-tms-cert.ps1 -UseCertificateAuth -Tenant "contoso.onmicrosoft.com".\o365-connect-tms-cert.ps1 -UseCertificateAuth -Organization "contoso.onmicrosoft.com" -AppId "<app-guid>" -CertificateThumbprint "<40-hex-thumbprint>".\o365-connect-tms-cert.ps1 -UseCertificateAuth -Tenant "contoso.onmicrosoft.com" -ValidateEntraOnConnect- "Specify exactly one mode": pass only one of generation/auth switches.
- Missing required auth values: provide explicit
Organization/Tenant,AppId, andCertificateThumbprintor ensure profile map has matching entry. - Thumbprint format error: verify 40-character SHA-1 hex string.
- Certificate not found: import PFX or regenerate cert on current machine.
- Graph device-code failure/invalid_scope: provide tenant-approved public client via
SetupClientId. - Teams authorization identity errors after connect: ensure service principal has required Entra directory role assignment.
Depending on mode/options, execution can produce:
- Local certificate in current user cert store.
- Exported certificate files (
.cer, optional.pfx). - Updated profile map JSON (
o365-tms-cert-auth.json). - Optional transcript log (
o365-connect-teams.txt).