Skip to content

Certificate based connection for Teams

directorcia edited this page Jul 1, 2026 · 1 revision

Purpose

This script provides a controlled certificate-based connection workflow for Microsoft Teams PowerShell, with two mutually exclusive operating modes:

  1. Generate local certificate materials for app-based authentication.
  2. 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.

Operating Modes

The script enforces exactly one mode per run:

  • -GenerateLocalCertificate
  • -UseCertificateAuth

If both or neither are supplied, execution stops with an error.

Key Runtime Behaviors

Path Resolution

At startup, the script resolves paths relative to its own location (not the caller's current working directory):

  • GeneratedCertOutputPath defaults to the parent directory of the script folder.
  • CertificateMapPath resolution order:
  1. Parent folder o365-tms-cert-auth.json
  2. Script folder o365-tms-cert-auth.json
  3. If not found, default write path becomes parent folder o365-tms-cert-auth.json

TLS and Logging

  • Enforces TLS 1.2 minimum for outbound network calls.
  • If -enableLog is used, starts transcript logging to o365-connect-teams.txt in the parent folder.

Module Handling

The script validates that the Microsoft Teams PowerShell module is available:

  1. Checks installation status.
  2. If missing, can prompt to install (unless -noprompt is used).
  3. Performs elevated install/update by relaunching the same PowerShell host executable with RunAs and an encoded command payload.
  4. Optionally checks/update against PSGallery (unless -noupdate is used).
  5. Imports module before mode-specific operations.

Parameters and Functional Grouping

Execution Control

  • noprompt: Non-interactive preference; disables selection/input prompts.
  • noupdate: Skips module version check/update.
  • enableLog: Enables transcript logging.

Mode Selection

  • GenerateLocalCertificate
  • UseCertificateAuth

Certificate Generation Inputs

  • GeneratedCertSubject (default O365-TMS-AppAuth)
  • GeneratedCertYearsValid (default 2)
  • GeneratedCertOutputPath
  • ExportGeneratedPfx
  • GeneratedPfxPassword

Certificate Auth/Profile Inputs

  • Tenant
  • ProfileName
  • Organization
  • AppId
  • CertificateThumbprint
  • CertificateMapPath

Graph/Provisioning Inputs

  • GraphResourceAppId (default Microsoft Graph app id)
  • ProvisionEntraApp
  • AppDisplayName
  • SetupClientId
  • EntraDirectoryRoleName (default Teams Administrator)
  • ValidateEntraOnConnect
  • SkipEntraValidationOnConnect
  • CopyDeviceCodeToClipboard

Mode 1: GenerateLocalCertificate

Base Flow

  1. Validates and creates output directory if needed.
  2. Creates a self-signed RSA 2048 / SHA-256 certificate in Cert:\CurrentUser\My.
  3. Sets certificate friendly name.
  4. Exports .cer public certificate file.
  5. Optionally exports .pfx if -ExportGeneratedPfx is set:
  • Uses GeneratedPfxPassword if provided.
  • Prompts for password if allowed and missing.
  • Throws if password still unavailable.
  1. Outputs generated thumbprint and export paths.

Optional Entra Provisioning (-ProvisionEntraApp)

When enabled, the script extends the generation flow to configure cloud prerequisites:

  1. Resolves/collects tenant identifier (Tenant required in non-prompt mode).
  2. Obtains delegated Graph token via device-code flow.
  3. Resolves Graph service principal and required app roles for Teams scenarios.
  4. Gets or creates app registration by display name.
  5. Uploads generated certificate as key credential if not already present.
  6. Ensures requiredResourceAccess includes expected Graph app roles.
  7. Gets or creates service principal for the app.
  8. Assigns Graph app roles (admin consent path).
  9. Ensures Entra directory role assignment for the app service principal.
  10. Writes or updates a profile entry in the JSON profile map.
  11. Prints provisioning summary and a ready-to-run connect command.

Profile Map Update Characteristics

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.

Mode 2: UseCertificateAuth

Input Resolution

Before connection, the script attempts to resolve missing values from profile map:

  • Filters profile candidates by ProfileName, Tenant, and/or Organization.
  • 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 Tenant as alias for Organization in cert-auth mode.
  • Validates required values are present: Organization/Tenant, AppId, CertificateThumbprint.

Certificate Validation

  1. Normalizes thumbprint (strip whitespace).
  2. Validates SHA-1 thumbprint format (40 hex chars).
  3. Verifies cert exists in Cert:\CurrentUser\My.
  4. Rejects expired cert.
  5. Warns when expiration is <= 30 days.

Optional Entra Pre-Validation

If -ValidateEntraOnConnect is enabled (and not overridden by -SkipEntraValidationOnConnect):

  1. Runs device-code Graph auth.
  2. Ensures app service principal exists.
  3. Ensures configured Entra directory role is assigned.
  4. Waits briefly for role propagation.

If this pre-check fails, script warns and continues to Teams connect attempt.

Session Reuse and Connection

  1. Checks existing Teams online session if cmdlet is available.
  2. If existing session appears to target requested tenant/org, skips reconnect.
  3. Otherwise runs Connect-MicrosoftTeams with:
  • -TenantId
  • -ApplicationId
  • -CertificateThumbprint
  1. On success, prints connected tenant details and certificate/app details.

Detailed Function-Level Operations

Invoke-ElevatedPowerShellCommand

Executes elevated module management commands using encoded command text to avoid quoting/escaping issues through UAC boundary.

Resolve-TeamsCertificateProfile

Loads and filters profile map entries from JSON and optionally prompts for profile selection if multiple matches remain.

New-TeamsLocalCertificate

Creates local self-signed cert and exports .cer and optional .pfx artifacts.

Get-DeviceCodeGraphToken

Runs OAuth 2.0 device code flow:

  1. Normalizes tenant input.
  2. Tries configured client id, then fallback public clients.
  3. Shows verification URI + user code (optionally clipboard copy).
  4. Polls token endpoint until success/timeout/decline.
  5. Returns access token.

Invoke-TeamsGraphRequest

Graph REST wrapper with retry/backoff for transient failures (429/5xx and throttling-like errors).

Get-OrCreateTeamsEntraServicePrincipal

Ensures service principal exists for target app id.

Get-TeamsProvisioningRoleTargets

Resolves Graph SP and required app-role ids used by provisioning.

Set-TeamsEntraRequiredResourceAccess

Patches app registration requiredResourceAccess with missing Graph roles.

Set-TeamsEntraAppRoleAssignments

Assigns app roles to service principal with skip logic for already-granted roles.

Set-TeamsEntraDirectoryRoleAssignment

Finds or activates directory role, then ensures membership for app service principal.

Set-TeamsProfileMapEntry

Concurrency-safe profile map update with lock, merge/replace logic, and atomic write strategy.

Get-OrCreateTeamsEntraApplication

Gets or creates app registration and ensures certificate key credential exists.

Resolve-TeamsTenantId

Attempts tenant normalization or tenant-id resolution via OpenID metadata.

Get-TeamsCertClientAssertionToken

Builds signed client assertion JWT from local certificate and requests app-only Graph token.

Write-TeamsConnectedTenant

Attempts to determine active tenant from Teams/Graph context and warns on mismatch with requested organization.

Write-TeamsCertConnectionDetails

Prints local certificate details and, if possible, Entra app key-credential details for match verification.

Error Handling and Exit Semantics

  • Script uses try/catch/finally at top level.
  • Fatal failures return exit code 1 and print reason.
  • Success in generation/auth flows returns exit code 0 where explicit exit is used.
  • If Teams connection was opened and an error occurs afterward, script attempts cleanup via Disconnect-MicrosoftTeams.
  • Transcript is always stopped in finally if logging was enabled.

Security and Operational Notes

  • 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.

Practical Run Examples

Generate local certificate only

.\o365-connect-tms-cert.ps1 -GenerateLocalCertificate -GeneratedCertSubject "Contoso-TeamsAuth"

Generate + export PFX

.\o365-connect-tms-cert.ps1 -GenerateLocalCertificate -ExportGeneratedPfx

Generate + provision Entra app + write profile map

.\o365-connect-tms-cert.ps1 -GenerateLocalCertificate -ProvisionEntraApp -Tenant "contoso.onmicrosoft.com"

Connect using profile map resolution

.\o365-connect-tms-cert.ps1 -UseCertificateAuth -Tenant "contoso.onmicrosoft.com"

Connect with explicit values

.\o365-connect-tms-cert.ps1 -UseCertificateAuth -Organization "contoso.onmicrosoft.com" -AppId "<app-guid>" -CertificateThumbprint "<40-hex-thumbprint>"

Connect with Entra pre-check

.\o365-connect-tms-cert.ps1 -UseCertificateAuth -Tenant "contoso.onmicrosoft.com" -ValidateEntraOnConnect

Troubleshooting Quick Reference

  • "Specify exactly one mode": pass only one of generation/auth switches.
  • Missing required auth values: provide explicit Organization/Tenant, AppId, and CertificateThumbprint or 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.

Expected Artifacts

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).

Clone this wiki locally