UptimeHunt Docs
OrganizationsSingle Sign-On

SSO with GitHub

Use GitHub organization membership for authentication with the UptimeHunt platform GitHub App.

SSO with GitHub

Overview

UptimeHunt uses the platform GitHub App ("Continue with GitHub") for GitHub-based sign-in. Members of your GitHub organization sign in with the platform-wide GitHub button — no per-organization OAuth App to register, no client ID or secret to copy.

Membership is verified in real time through the UptimeHunt GitHub App installed on your GitHub organization. All GitHub settings live under Organization → Workspace settings → Authentication.

GitHub differs from corporate IdPs: it asserts the user's own (often personal) email addresses, not addresses under a domain you control. GitHub sign-in is therefore never email-routed — entering an email on the login page does not offer a GitHub route until an account already exists — and domain verification plays no role for GitHub.

Deployment requirement

GitHub sign-in requires the UptimeHunt platform GitHub App to be configured at the deployment level. The UI indicates when it is unavailable.

Setup

Step 1 — Select GitHub as the sign-in provider

Go to Organization → Workspace settings → Authentication. In the provider dropdown, select GitHub. The GitHub settings card appears below.

Step 2 — Enter your GitHub organization name

UI field: GitHub organization

Hint: "Only ACTIVE members of this GitHub organization may join. Requires the platform GitHub App installed there; membership is verified through the App installation. Leave empty to disable mapping."

Enter your GitHub organization's login name — the slug from github.com/{your-org}. For example, for github.com/acme-engineering enter acme-engineering.

Setting this field opts the organization into platform GitHub membership mapping; clearing it switches mapping off.

API:

curl -X PATCH https://app.uptimehunt.io/api/v1/orgs/acme \
  -H "Authorization: Bearer {access_token}" \
  -H "Content-Type: application/json" \
  -d '{"github_org": "acme", "github_default_role": "member", "github_auto_join": false}'

Step 3 — Install the UptimeHunt GitHub App

A GitHub organization owner installs the UptimeHunt GitHub App on your GitHub organization (GitHub → your organization → Settings → GitHub Apps) — a one-time, explicit approval. The App asks only for the Organization members: read permission, which is how UptimeHunt verifies membership.

Why a GitHub App?

OAuth tokens are subject to GitHub's OAuth app access restrictions (on by default for new GitHub organizations): an app cannot see a user's membership of a restricted organization until that org's admin approves the app — an invisible failure mode. A GitHub App installation is a single explicit grant by the org admin, after which UptimeHunt checks membership with the installation token, unaffected by per-user access restrictions. Membership checks fail closed: if GitHub cannot confirm an active membership, access is not granted.

Step 4 — Check App installation

After entering the GitHub organization name, the Check App installation button appears. Click it to verify the UptimeHunt GitHub App is installed on your GitHub organization before the first save.

The button calls the SSO configuration test (POST /api/v1/orgs/{slug}/sso/test) and evaluates the github_app_installed check — it confirms the App is installed on the named GitHub organization. The result appears inline:

  • A green status indicates the App is installed and membership verification is working.
  • A yellow warning gives the specific problem (not installed, or platform App not configured on this deployment).

API equivalent:

curl -X POST https://app.uptimehunt.io/api/v1/orgs/acme/sso/test \
  -H "Authorization: Bearer {access_token}"

The response's checks array includes {"name": "github_app_installed", "ok": true|false, "detail": "..."}.

Step 5 — Configure the toggles

Auto-join verified members (checkbox)

Hint: "On: verified GitHub-organization members join automatically when they sign in with GitHub. Off: sign-in only offers this organization — members confirm the join explicitly."

  • Off (default): eligible organizations appear under "Available via GitHub" in the organization switcher and in a post-sign-in card. The member clicks Join to enroll explicitly.
  • On: the member is added automatically at sign-in. Still verified against GitHub in real time and counted against the org's member limit.

Default role for GitHub-mapped members (select)

Hint: "Granted to verified members matched by no team-role rule below — overridden by the team-role mapping and its fall-through policy."

Options: Member (default), Admin. Cannot be set to Owner here; use the Team-role mapping to grant Owner to a specific GitHub team.

Click Save GitHub settings to persist all settings.

How members get in

  1. The member signs in with the platform-wide Sign in with GitHub button.
  2. After sign-in the platform checks GitHub membership in real time for every organization that has named a GitHub organization.
  3. If auto-join is off (the default): eligible organizations appear under "Available via GitHub"; the member clicks Join to enroll.
  4. If auto-join is on: the member is added automatically.
  5. Every join (explicit or auto) is verified against GitHub in real time and recorded in the audit log (member.joined).

API reference:

EndpointPurpose
GET /api/v1/auth/github/orgsThe signed-in GitHub account's mapped organizations with status (member, eligible, dedicated_account_required)
POST /api/v1/auth/github/orgs/{slug}/joinExplicit join (201; idempotent)

GET /api/v1/auth/github/orgs status values:

statusMeaning
memberAlready a member of this UptimeHunt organization
eligibleVerified active GitHub-org member; can join
dedicated_account_requiredThe organization has require_dedicated_accounts enabled — the platform-GitHub path refuses mapping. The member must sign in through the organization's own IdP instead

Join error codes:

CodeHTTPMeaning
github_realm_required403The caller's account is not a platform GitHub (social:github) realm account — only accounts signed in via the platform "Continue with GitHub" button can use mapped-org join
github_app_not_configured403The platform GitHub App is not configured at the deployment level — GitHub membership mapping is unavailable on this instance
not_found404The organization slug does not exist, or the organization has no GitHub mapping configured (github_org is empty) — unknown orgs and unmapped orgs answer identically (no mapping-existence oracle)
dedicated_account_required403The organization requires dedicated accounts — the platform-GitHub path is not permitted; use the organization's own sign-in
github_app_not_installed409The platform GitHub App is not installed on the GitHub organization
github_unavailable502GitHub API is unreachable
github_org_mismatch403Not an active member of the configured GitHub organization
team_role_denied403A GitHub team-role rule matches the member's teams and the result denies access to this organization
team_lookup_failed403GitHub's teams API could not be reached to verify team membership, and the organization's unmapped-members policy is Refuse sign-in — a new mapping cannot be created while teams are unverifiable
member_cap_reached403The organization's member limit has been reached

One account, many organizations

The same GitHub identity holds ordinary memberships in every organization that has configured GitHub mapping. Removing the member from the GitHub organization stops new joins immediately; their existing UptimeHunt membership is removed through normal offboarding.

Team-Role Mapping

The Team-role mapping section (Organization → Workspace settings → Authentication, below the GitHub organization settings) maps a member's GitHub team membership to a UptimeHunt role. It is an org-level mapping evaluated at every sign-in.

Configuring rules

The editor shows an ordered list of rules. Each row pairs a Team slug (the slug from the team's GitHub URL: github.com/orgs/acme/teams/platform-leadsplatform-leads) with a role. Use the move up/move down controls to reorder.

  • First match wins. Rules are evaluated top-down; the first team the member belongs to decides their role — order rules most-privileged first.
  • Team slug constraints: max 39 characters, only letters, digits, hyphens and underscores (^[A-Za-z0-9_-]+$). A duplicate team slug is rejected (it could never win under first-match).
  • Up to 50 rules.
  • Owner is permitted but warned. The editor shows a warning when a rule grants Owner. The Default role for GitHub-mapped members select (above) cannot be set to Owner; only an explicit team rule can grant it.

Members matched by no rule (select):

UI labelEffect
Use default role (default)Fall back to Default role for GitHub-mapped members
MemberGrant the Member role
AdminGrant the Admin role
Refuse sign-inDeny the organization entirely — the member cannot join

Refuse sign-in is strict

With Refuse sign-in selected, a verified GitHub member who is in none of the mapped teams is denied access. New just-in-time sign-ins are also refused when the teams API cannot be read (lookup failure) — a brand-new account cannot be provisioned while team membership is unverifiable.

Click Save GitHub settings after configuring the rules.

Re-sync, the last-Owner guard, and lookup failures

  • Re-synced on every sign-in. The mapping is re-evaluated each time a member signs in — moving someone between GitHub teams updates their UptimeHunt role at their next sign-in. A role change emits github.team_role.applied.
  • Last-Owner guard. The organization's sole Owner is never locked out by team mapping. A mapping result that would demote the only Owner is skipped; a Refuse sign-in result for the only Owner does not refuse the sign-in — they keep their role and sign in normally.
  • Lookup failures fail safe, asymmetrically. If GitHub's teams API cannot be read at sign-in:
    • Existing members keep their current role — the sign-in continues and github.team_role.lookup_failed is recorded.
    • New JIT sign-ins are refused when the unmapped-members policy is Refuse sign-in. Under any other policy, the new member is provisioned with the default role and the fallback is recorded.

How teams are looked up

Each rule's team is checked with the platform GitHub App installation token (GET /orgs/{github_org}/teams/{team_slug}/memberships/{username}) — this is why the App needs Organization members: read.

Example

For a github_org of acme, ordered most-privileged-first:

#Team slugRole
1platform-leadsOwner
2sreAdmin
3engineeringMember

With Members matched by no rule set to Refuse sign-in: a member of both sre and engineering becomes an Admin (rule 2 wins before rule 3); a member of only platform-leads becomes an Owner; a verified GitHub member in none of the three teams is denied access.

API

curl -X PATCH https://app.uptimehunt.io/api/v1/orgs/acme \
  -H "Authorization: Bearer {access_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "github_team_role_rules": [
      {"team_slug": "platform-leads", "role": "owner"},
      {"team_slug": "sre", "role": "admin"},
      {"team_slug": "engineering", "role": "member"}
    ],
    "github_team_roles_unmapped_policy": "deny"
  }'
FieldDescription
github_team_role_rulesOrdered list of {"team_slug", "role"} objects — first match wins. Empty list = mapping off. At most 50; duplicate team_slug rejected
github_team_roles_unmapped_policy'' (Use default role), member, admin, or deny (Refuse sign-in). Only consulted while github_team_role_rules is non-empty

Audit events

EventWhen
github.team_mapping.updatedThe rule list or the unmapped-members policy was changed
github.team_role.appliedA sign-in re-synced a member's role from their team membership; team_slug is the matched rule's team slug (or null when the unmapped policy decided)
github.team_role.deniedA Refuse sign-in policy refused the join/sign-in
github.team_role.lookup_failedGitHub's teams API could not be read at sign-in; detail depends on whether this is an existing member (keeps role), a new JIT under Refuse sign-in (refused), or a new JIT under another policy (provisioned with default role)

Troubleshooting

SymptomLikely cause
An eligible member doesn't see the organization after GitHub sign-inThe UptimeHunt GitHub App is not installed on the GitHub organization (click Check App installation in the Authentication tab), the member's GitHub membership is not active (pending invitation), or they signed in with a different login method (password/Google)
github_app_not_installed (409) on joinInstall the UptimeHunt GitHub App on the GitHub organization (step 3)
Check App installation button returns a warningThe platform GitHub App is not configured on this deployment — GitHub SSO cannot be enabled here
Sign-in rejected with github_org_mismatchThe GitHub account is not an active member of the configured GitHub organization (a pending GitHub invitation doesn't count)
The GitHub organization field and Save GitHub settings are greyed outThe platform GitHub App is not configured on this deployment
Login page never offers a GitHub route after entering an emailExpected until that user's GitHub-linked account exists — GitHub is not email-routed. Use the Use single sign-on option, or sign in with the platform GitHub button
A member got the wrong role from Team-role mappingRules are first-match, ordered top-down — a more-privileged rule earlier in the list wins. Reorder with move up/move down. The role re-syncs at the member's next sign-in, not retroactively
A member in the right team is refused sign-inWith Refuse sign-in selected and the member in no mapped team — confirm the GitHub team slug exactly matches the URL slug, not the display name. For new accounts, a GitHub teams API failure also refuses provisioning under this policy
The sole Owner's role didn't change after moving GitHub teamsThe last-Owner guard refuses any mapping result that would demote the only Owner; promote another member to Owner first

On this page