Skip to content

SSOLogoutParams asks for a session ID, but the endpoint requires a profile ID #605

Description

@hyeomans

SSOLogout asks callers to provide SSOLogoutParams.SessionID, but it sends that value to POST /sso/logout/authorize as profile_id.

The standalone SSO logout endpoint requires an SSO profile ID such as prof_123. An AuthKit session ID such as session_123 identifies a different resource and cannot be used in its place.

Current behavior

A caller following the public Go API will naturally write:

logoutURL, err := client.SSOLogout(ctx, workos.SSOLogoutParams{
	SessionID: "session_123",
})

The helper then sends this request body to WorkOS:

{
  "profile_id": "session_123"
}

This happens because sso_helpers.go assigns params.SessionID to the generated SSOAuthorizeLogoutParams.ProfileID field.

The endpoint expects a profile ID instead:

{
  "profile_id": "prof_123"
}

There are two different IDs involved:

  • session_123 identifies an AuthKit login session.
  • prof_123 identifies a user profile in the standalone SSO product.

They are not interchangeable. The SDK currently asks for one kind of identifier and places it in a field meant for another. It is like a form asking for a phone number and then submitting that value as a Social Security number. The JSON field name is correct, but the SDK told the caller to supply the wrong value.

If this helper is meant to perform standalone SSO logout, it should accept a profile ID. If it is meant to end an AuthKit session using a session_... ID, it should use the separate /user_management/sessions/logout endpoint instead.

Expected behavior

The public helper should ask for a profile ID:

logoutURL, err := client.SSOLogout(ctx, workos.SSOLogoutParams{
	ProfileID: "prof_123",
})

It should then send:

{
  "profile_id": "prof_123"
}

Test gap

TestSSOLogout_WithMockServer passes sess_123, but the mock server checks only the HTTP method and path. It does not decode the request body or verify the value sent as profile_id.

A request-body assertion would have caught the mismatch.

Possible fix

Add ProfileID to SSOLogoutParams and use it for the authorize request. To avoid an immediate source-breaking change, keep SessionID temporarily as a deprecated fallback:

type SSOLogoutParams struct {
	ProfileID string

	// Deprecated: use ProfileID.
	// Despite its name, this value must contain an SSO profile ID.
	SessionID string

	ReturnTo *string
}

The implementation should return a clear error if neither identifier is supplied. If both fields contain different values, it should also return an error rather than silently choosing one.

Tests should decode the outgoing request body and cover the new ProfileID field, the deprecated compatibility path, missing identifiers, conflicting identifiers, and the existing ReturnTo behavior.

This fix belongs in the hand-maintained sso_helpers.go and sso_helpers_test.go files. The generated sso.go file already models the endpoint correctly and should not be edited.

Relevant code

  • sso_helpers.go:153 defines SSOLogoutParams.SessionID.
  • sso_helpers.go:165 assigns that value to SSOAuthorizeLogoutParams.ProfileID.
  • sso.go:149 correctly defines the generated endpoint parameter as ProfileID.

Reference

The WorkOS SSO logout reference documents profile_id as the required request field: https://workos.com/docs/reference/sso/logout.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions