← All Articles

OIDC and Microsoft Entra ID Setup

What OIDC Gives You

With OIDC enabled, IMTerm shows a Sign in with Microsoft button on the login page (or whichever provider you configure). Users log in with their existing Windows/Microsoft credentials - the same username and password they use for email, Teams, and SharePoint. No separate IMTerm password to remember, reset, or expire.

From an administrator's perspective: user accounts are managed centrally in Azure AD. When an employee leaves the organization and their Azure AD account is disabled, they immediately lose access to IMTerm - no manual deprovisioning required.

Key message: users log in to IMTerm with their existing Windows credentials. IT manages access in Azure AD/Entra ID, exactly as they do for every other Microsoft-integrated application.

Entra ID App Registration

Get a Dev Tenant (for testing)

If you do not have an Entra ID/Azure AD tenant to test with, Microsoft offers a free developer tenant through the Microsoft 365 Developer Program at developer.microsoft.com/microsoft-365/dev-program. This gives you a full Entra ID environment with test users and groups, no production risk.

Register the App

  1. Sign in to the Azure portal and navigate to Azure Active Directory > App registrations > New registration.
  2. Name: IMTerm (or your organization's preferred name).
  3. Supported account types: Accounts in this organizational directory only (single tenant).
  4. Redirect URI: choose Web and enter https://imterm.corp.com/auth/callback (replace with your IMTerm URL).
  5. Click Register.

After registration, collect these values from the Overview page:

  • Application (client) ID - you will use this as client_id
  • Directory (tenant) ID - used in the issuer URL

Create a client secret:

  1. Go to Certificates & secrets > New client secret.
  2. Set an expiry (24 months recommended; add a calendar reminder to rotate before expiry).
  3. Copy the secret value immediately - it is only shown once.

Add API permissions:

  1. Go to API permissions > Add a permission > Microsoft Graph > Delegated permissions.
  2. Add: openid, profile, email, User.Read.
  3. For group-based role mapping, also add GroupMember.Read.All (requires admin consent).
  4. Click Grant admin consent.

config.yaml OIDC Section

auth:
  provider: oidc
  oidc:
    # Entra ID (Azure AD) issuer URL - replace {tenant-id} with your Directory ID
    provider_url: "https://login.microsoftonline.com/{tenant-id}/v2.0"

    # Application (client) ID from app registration
    client_id: "{application-client-id}"

    # Client secret value - use an environment variable, never a plain string in production
    client_secret: "${OIDC_CLIENT_SECRET}"

    # Must exactly match the redirect URI registered in Azure
    redirect_url: "https://imterm.corp.com/auth/callback"

    scopes: ["openid", "profile", "email", "offline_access"]

    # Claim to use as the IMTerm username (preferred_username = UPN, e.g. jsmith@corp.com)
    username_claim: "preferred_username"

Store the secret in an environment variable rather than directly in the YAML file:

# In /etc/systemd/system/imterm.service [Service] block:
Environment=OIDC_CLIENT_SECRET=your-secret-here

# Or in a .env file sourced before starting imterm:
export OIDC_CLIENT_SECRET=your-secret-here

Group-to-Role Mapping

Map Azure AD groups to IMTerm roles using the group Object ID (not the display name). Find the Object ID in Azure AD > Groups > select the group > Overview.

auth:
  provider: oidc
  oidc:
    # ... (as above)
    groups_claim: "groups"    # Azure AD includes group Object IDs in this claim

  role_mapping:
    admin: ["{object-id-of-IMTerm-Admins-group}"]
    user:  ["{object-id-of-IMTerm-Users-group}"]

If the groups claim is not present in the token, you need to enable group claims in the app manifest. In Azure portal: App registrations > your app > Token configuration > Add groups claim > select "Security groups".

Users who are not in any mapped group receive no role and cannot log in. Add a catch-all by mapping the All Users group or the Domain Users group to the user role.


Testing Options

There are four ways to test OIDC with IMTerm, from lowest to highest friction:

Option A: mockoidc (recommended for development)

IMTerm ships a built-in mock OIDC provider for development and CI testing. Start it with:

go run ./cmd/mockoidc --port 9999

Configure IMTerm to use it:

auth:
  provider: oidc
  oidc:
    provider_url: "http://localhost:9999"
    client_id: "mock-client"
    client_secret: "mock-secret"
    redirect_url: "http://localhost:8080/auth/callback"

The mock provider presents a login form where you can type any username and choose any role. No external account needed. Useful for verifying the OIDC redirect flow, role mapping logic, and session creation without touching a real IdP.

Option B: Google (personal account)

Use a personal Google account to test OIDC with a real provider. In Google Cloud Console, create an OAuth 2.0 Client ID (Web application), add your redirect URI, and configure IMTerm:

auth:
  provider: oidc
  oidc:
    provider_url: "https://accounts.google.com"
    client_id: "{google-client-id}.apps.googleusercontent.com"
    client_secret: "${OIDC_CLIENT_SECRET}"
    redirect_url: "https://imterm.corp.com/auth/callback"
    username_claim: "email"

Google OIDC does not include group membership in tokens. Use it to verify the login flow but not group-to-role mapping.

Option C: Entra ID (production path)

Follow the app registration steps above. Use a Microsoft 365 developer tenant if you do not have access to your production Azure AD. This tests the exact flow your users will see.

Tip: always test in a private browser session (Ctrl+Shift+N in Chrome, Ctrl+Shift+P in Firefox). A regular session may have a cached Microsoft SSO cookie that skips the login page entirely, hiding any configuration errors.

Option D: button-only (UI testing without a working IdP)

To test that the "Sign in with Microsoft" button appears correctly on the login page without configuring a working OIDC backend, set provider_url to a placeholder URL. IMTerm will render the login button but clicking it will result in an error (expected in this mode). Useful for UI/UX review or screenshot capture.

auth:
  provider: oidc
  oidc:
    provider_url: "https://placeholder.example.com"
    client_id: "test"
    client_secret: "test"
    redirect_url: "https://imterm.corp.com/auth/callback"

Troubleshooting

redirect_uri_mismatch error

The redirect_url in config.yaml must exactly match the redirect URI registered in Azure, including the scheme (https://), hostname, and path. A trailing slash difference causes this error. Double-check both values and ensure they are character-for-character identical.

User logs in but has no role

Check the groups claim in the OIDC token. Use a tool like jwt.ms to decode the token and verify group Object IDs are present. If the claim is empty, verify that group claims are configured in the app manifest (Token configuration > Add groups claim).

AADSTS700016: Application not found

The client_id does not match any app in the tenant. Verify the Application (client) ID and that the provider_url uses the correct tenant ID. Single-tenant apps only accept tokens from their own tenant.

Login works in private window but not regular window

A cached Microsoft SSO session in the regular browser window is interfering. This is expected behavior - clear cookies or always test in a private/incognito window during setup.