Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Oct 9, 2025

Problem

Semaphore was failing OIDC authentication with Okta (and potentially other identity providers) with a persistent invalid_client error during the Authorization Code Exchange step. The root cause was a protocol mismatch in how client credentials are transmitted to the token endpoint:

  • Semaphore's default behavior: Sends credentials via Authorization: Basic header (client_secret_basic)
  • Okta's requirement: Expects credentials in the POST body (client_secret_post)

This mismatch caused Okta to reject authentication requests even when all other configuration (Issuer URL, Redirect URI, Client ID/Secret) was correct.

Solution

This PR adds support for configuring the token endpoint authentication method in OIDC provider configurations. Users can now explicitly specify how credentials should be sent during the OAuth2 token exchange.

Changes

  1. New Configuration Field: Added token_endpoint_auth_method to the OidcProvider struct

    • Accepts: "client_secret_post", "client_secret_basic", or empty (auto-detect)
    • Fully backward compatible - existing configs work unchanged
  2. Authentication Logic: Modified getOidcProvider() to configure the OAuth2 endpoint's AuthStyle based on provider settings:

    switch provider.TokenEndpointAuthMethod {
    case "client_secret_post":
        endpoint.AuthStyle = oauth2.AuthStyleInParams
    case "client_secret_basic":
        endpoint.AuthStyle = oauth2.AuthStyleInHeader
    default:
        endpoint.AuthStyle = oauth2.AuthStyleAutoDetect
    }
  3. Comprehensive Testing: Added 3 new tests covering all authentication methods (all tests passing)

  4. Documentation: Created example Okta configuration with detailed setup instructions and troubleshooting guide

Usage

For Okta (or other providers requiring POST body credentials):

{
  "oidc_providers": {
    "okta": {
      "display_name": "Okta",
      "provider_url": "https://your-domain.okta.com",
      "client_id": "YOUR_CLIENT_ID",
      "client_secret": "YOUR_CLIENT_SECRET",
      "token_endpoint_auth_method": "client_secret_post"
    }
  }
}

Or via environment variable:

export SEMAPHORE_OIDC_PROVIDERS='{"okta":{..., "token_endpoint_auth_method":"client_secret_post"}}'

Technical Details

The implementation uses the Go golang.org/x/oauth2 library's built-in AuthStyle support:

  • AuthStyleInParams (1) - Sends credentials in POST body (client_secret_post)
  • AuthStyleInHeader (2) - Sends credentials in Authorization header (client_secret_basic)
  • AuthStyleAutoDetect (0) - Auto-detect based on provider (default, maintains backward compatibility)

Backward Compatibility

Full backward compatibility maintained:

  • Existing configurations without token_endpoint_auth_method continue to work unchanged
  • Default behavior remains auto-detect
  • No breaking changes to API or configuration schema

Testing

  • ✅ All login tests passing (8/8)
  • ✅ Go linter: no issues
  • ✅ Backend compilation: successful
  • ✅ Backward compatibility verified

Fixes #[issue_number]

Original prompt

This section details on the original issue you should resolve

<issue_title>Problem: Okta authentication fails</issue_title>
<issue_description>### Issue

The Semaphore UI application (running on Google Cloud Run) is failing the OpenID Connect (OIDC) authentication flow with a persistent invalid_client error during the Authorization Code Exchange step with the identity provider (Okta). All external configurations (Issuer URL, Redirect URI, and Client Authentication Method on the provider's side) have been validated as correct.

The root cause is a protocol mismatch: the Semaphore application is likely sending credentials using the standard method, which conflicts with the provider's stricter requirement.

Component Value/Status
Application Semaphore UI (semaphore/pro/server:latest)
Deployment Google Cloud Run (Project ID removed)
IDP Okta (Domain removed)
Error level=error msg="oauth2: "invalid_client" "Client authentication failed. Either the client or the client credentials are invalid."
Token Endpoint /oauth2/v1/token

Confirmed Configuration (Correct)

The following parameters have been confirmed to be correct and match the identity provider's expectations:

  • Issuer URL: Confirmed correct (Base URL removed).

  • Redirect URI: Confirmed set in Okta (Domain removed).

  • Okta Client Auth Method: client_secret_post (Confirmed by Administrator).

  • Client Credentials: Validated via manual external test (e.g., Postman).

Observed Behavior (The Protocol Mismatch)

The error strongly indicates that the Semaphore application is defaulting to the standard OIDC method for confidential clients:

  • Semaphore's Action (Likely Default): The application is sending the Client ID and Secret in the Authorization: Basic ... HTTP header (i.e., using client_secret_basic).

  • Okta's Requirement (Confirmed): The identity provider is strictly configured to expect the credentials to be in the body of the POST request (i.e., using client_secret_post.

  • Because the method of authentication delivery does not match the provider's configuration, Okta rejects the request with the generic invalid_client error.

Feature Request: Request that the Semaphore application either:

  • Explicitly implement support for honoring the client_secret_post method.

  • Introduce a configuration option (e.g., via environment variable) that allows users to explicitly set the desired token_endpoint_auth_method to either basic or post.

Impact

Web-Frontend (what users interact with)

Installation method

Docker

Database

Postgres

Browser

Chrome

Semaphore Version

v2.16.29-d14fa6b-1757160953

Ansible Version

Logs & errors

No response

Manual installation - system information

No response

Configuration

No response

Additional information

No response</issue_description>

Comments on the Issue (you are @copilot in this section)

Fixes #3348


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@Copilot Copilot AI assigned Copilot and fiftin Oct 9, 2025
@fiftin fiftin marked this pull request as ready for review October 9, 2025 19:57
@Copilot Copilot AI changed the title [WIP] Fix Okta authentication failure in Semaphore UI Add token_endpoint_auth_method configuration for OIDC providers to fix Okta authentication Oct 9, 2025
@Copilot Copilot AI requested a review from fiftin October 9, 2025 20:14
Copilot finished work on behalf of fiftin October 9, 2025 20:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Problem: Okta authentication fails

2 participants