Skip to content

fix(scim): Add scimType and status to SCIM error responses#117870

Merged
markstory merged 2 commits into
getsentry:masterfrom
Asynchronite:fix/sentry-scim-attributes
Jun 17, 2026
Merged

fix(scim): Add scimType and status to SCIM error responses#117870
markstory merged 2 commits into
getsentry:masterfrom
Asynchronite:fix/sentry-scim-attributes

Conversation

@Asynchronite

@Asynchronite Asynchronite commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Sentry's SCIM error responses were missing two members that RFC 7644
§3.12
requires:

  • status — the HTTP status code, as a string, on every SCIM error body.
  • scimType"uniqueness" for unique-attribute collisions.

Why this matters

When an IdP provisions a user whose email already exists in the org, Sentry
correctly returns 409, but the body omits scimType: "uniqueness". Spec-
compliant IdPs (e.g. Microsoft Entra) rely on that value to recognize "this user
already exists" and fall back from POST to PATCH/PUT against the existing
record. Without it, the operation hard-fails. This is the normal initial-sync
path: any org that had SAML2 SSO before enabling SCIM already has members (via
JIT or manual invite), so the IdP's first pass POSTs users that already exist.

Before

{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
  "detail": "User already exists in the database."
}

After

{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
  "scimType": "uniqueness",
  "status": "409",
  "detail": "User already exists in the database."
}

Changes

  • Add status (string) in the shared SCIMApiError builder and the static SCIM
    error constants, so all SCIM error responses are compliant.
  • Set scimType: "uniqueness" on both unique-attribute 409 paths: duplicate
    user (member create) and duplicate team/group slug (team create).
  • The team-create duplicate path previously returned a non-SCIM body (no schema
    URN); it now raises SCIMApiError for a proper SCIM error envelope.

Additive only: the 409 status code, detail text, and schema URN are
unchanged, so existing clients are unaffected.

Tests

  • Updated the SCIM member/team endpoint tests to assert the new scimType /
    status fields on the uniqueness cases.
  • Added a regression test confirming non-uniqueness SCIM errors still return
    valid bodies that include a string status (and no spurious scimType).

Closing Issues

Closes #117860.

Legal Boilerplate

Look, I get it. The entity doing business as "Sentry" was incorporated in the State of Delaware in 2015 as Functional Software, Inc. and is gonna need some rights from me in order to utilize my contributions in this here PR. So here's the deal: I retain all rights, title and interest in and to my contributions, and by keeping this boilerplate intact I confirm that Sentry can use, modify, copy, and redistribute my contributions, under Sentry's choice of terms.

Asynchronite and others added 2 commits June 16, 2026 23:50
SCIM error bodies were missing two members RFC 7644 §3.12 requires:
`status` (the HTTP status code as a string) on every error, and
`scimType` on uniqueness collisions. Without `scimType: "uniqueness"`,
spec-compliant IdPs (e.g. Microsoft Entra) can't recognize a 409 as a
duplicate and fall back from POST to PATCH/PUT, so initial-sync of
members that already exist (via SAML JIT or manual invite) hard-fails.

Add `status` in the shared SCIMApiError builder and the static SCIM
error constants so all SCIM error responses are compliant, and set
`scimType: "uniqueness"` on the duplicate-user (409) and duplicate
team/group slug (409) paths. The team-create duplicate path previously
returned a non-SCIM body with no schema URN; it now raises SCIMApiError
for a proper error envelope.

Additive only: the 409 status code, detail text, and schema URN are
unchanged.
@Asynchronite Asynchronite requested a review from a team as a code owner June 16, 2026 21:57
@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label Jun 16, 2026
@Asynchronite

Copy link
Copy Markdown
Contributor Author

All tests pass! If someone would be so kind as to add the Trigger: getsentry tests label I would appreciate it a great ton!

@markstory markstory added the Trigger: getsentry tests Once code is reviewed: apply label to PR to trigger getsentry tests label Jun 17, 2026
@markstory markstory self-assigned this Jun 17, 2026
@markstory markstory merged commit cefb96c into getsentry:master Jun 17, 2026
114 of 117 checks passed
@markstory

Copy link
Copy Markdown
Member

Thank you 🎉

@Asynchronite

Copy link
Copy Markdown
Contributor Author

Thank you 🎉

Np <3
Btw, what does the vercel job do?

@Asynchronite Asynchronite deleted the fix/sentry-scim-attributes branch June 18, 2026 02:21
sehr-m pushed a commit that referenced this pull request Jun 23, 2026
## Summary

Sentry's SCIM error responses were missing two members that [RFC 7644
§3.12](https://datatracker.ietf.org/doc/html/rfc7644#section-3.12)
requires:

- `status` — the HTTP status code, as a **string**, on every SCIM error
body.
- `scimType` — `"uniqueness"` for unique-attribute collisions.

### Why this matters

When an IdP provisions a user whose email already exists in the org,
Sentry
correctly returns **409**, but the body omits `scimType: "uniqueness"`.
Spec-
compliant IdPs (e.g. Microsoft Entra) rely on that value to recognize
"this user
already exists" and fall back from `POST` to `PATCH`/`PUT` against the
existing
record. Without it, the operation hard-fails. This is the normal
initial-sync
path: any org that had SAML2 SSO before enabling SCIM already has
members (via
JIT or manual invite), so the IdP's first pass POSTs users that already
exist.

### Before

```json
{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
  "detail": "User already exists in the database."
}
```

### After

```json
{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
  "scimType": "uniqueness",
  "status": "409",
  "detail": "User already exists in the database."
}
```

## Changes

- Add `status` (string) in the shared `SCIMApiError` builder and the
static SCIM
  error constants, so **all** SCIM error responses are compliant.
- Set `scimType: "uniqueness"` on both unique-attribute 409 paths:
duplicate
  user (member create) and duplicate team/group slug (team create).
- The team-create duplicate path previously returned a non-SCIM body (no
schema
  URN); it now raises `SCIMApiError` for a proper SCIM error envelope.

**Additive only:** the 409 status code, `detail` text, and schema URN
are
unchanged, so existing clients are unaffected.

## Tests

- Updated the SCIM member/team endpoint tests to assert the new
`scimType` /
  `status` fields on the uniqueness cases.
- Added a regression test confirming non-uniqueness SCIM errors still
return
valid bodies that include a string `status` (and no spurious
`scimType`).

## Closing Issues
Closes #117860.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components Trigger: getsentry tests Once code is reviewed: apply label to PR to trigger getsentry tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SCIM 409 on duplicate user omits scimType: "uniqueness", breaking spec-compliant provisioning of existing members

2 participants