Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Add Private Key JWT support for client credentials in Management API #528

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

ErwinSteffens
Copy link
Contributor

@ErwinSteffens ErwinSteffens commented Mar 18, 2025

🔧 Changes

This PR adds support for Client Credentials authentication using Private Key JWT for the Management API.

The [golang.org/x/oauth2](https://pkg.go.dev/golang.org/x/oauth2) package allows for customizing EndpointParams in the client credentials flow, which enables the use of Private Key JWT without direct support from the library. By using AuthStyleInParams and omitting ClientID and ClientSecret, these parameters are excluded from the request, which aligns with how Private Key JWT should work.

There is an open issue in x/oauth2 for first-class support of this feature, but it hasn’t seen recent progress. This implementation provides a practical workaround while staying idiomatic to the existing Auth0 SDK design.

If the approach looks good, I’ll follow up with test coverage.


✅ Usage Examples

🔐 Client credentials using Private Key JWT:

api, err := management.New(
    "your-tenant.auth0.com",
    management.WithClientCredentialsPrivateKeyJwt(
        context.Background(),
        "YOUR_CLIENT_ID",
        privateKey,
        "RS256",
    ),
)

🔐 Private Key JWT with custom audience:

api, err := management.New(
    "your-tenant.auth0.com",
    management.WithClientCredentialsPrivateKeyJwtAndAudience(
        context.Background(),
        "YOUR_CLIENT_ID",
        privateKey,
        "RS256",
        "https://custom-api.example.com",
    ),
)

📚 References


🔬 Testing

To test manually:

  1. Generate a key pair:

    openssl genrsa -out private.pem 2048
    openssl rsa -in private.pem -pubout > public.pub
  2. Create an Auth0 Application using the "Machine to Machine" flow.

  3. Configure Private Key JWT:

    • In the Auth0 Dashboard, enable "Private Key JWT" under Client Authentication Method.
    • Upload your public.pub as the client’s public key.
  4. Run the following test code (ensure private.pem is in the working directory):

package main

import (
	"context"
	"log"
	"os"

	"github.com/auth0/go-auth0/management"
)

func main() {
	privateKey, err := os.ReadFile("private.pem")
	if err != nil {
		log.Fatal(err)
	}

	api, err := management.New(
		"your-tenant.auth0.com",
		management.WithClientCredentialsPrivateKeyJwt(
			context.Background(),
			"YOUR_CLIENT_ID",
			privateKey,
			"RS256",
		),
	)
	if err != nil {
		log.Fatal(err)
	}

	clients, err := api.Client.List(context.Background(), management.Page(0), management.PerPage(10))
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("Auth0 clients: %+v", clients)
}

📝 Checklist

  • All new/changed functionality is covered by tests (or N/A)
  • Documentation is updated for all new/changed functionality (or N/A)

@developerkunal
Copy link
Contributor

Hi @ErwinSteffens,

I'll review the PR. Currently, we're exploring alternative ways to support this since the OAuth2 library doesn't provide this feature yet. However, if they add support in the future, we may reconsider our approach. I'll keep you updated on the next steps.

Thanks for your contribution!

@codecov-commenter
Copy link

codecov-commenter commented Apr 6, 2025

Codecov Report

Attention: Patch coverage is 87.50000% with 17 lines in your changes missing coverage. Please review.

Project coverage is 95.82%. Comparing base (e7b66a9) to head (636d182).

Files with missing lines Patch % Lines
management/management_option.go 0.00% 8 Missing ⚠️
internal/client/jwt_token_source.go 94.49% 4 Missing and 2 partials ⚠️
authentication/authentication.go 75.00% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #528      +/-   ##
==========================================
- Coverage   95.85%   95.82%   -0.04%     
==========================================
  Files          59       60       +1     
  Lines       11540    11639      +99     
==========================================
+ Hits        11062    11153      +91     
- Misses        359      366       +7     
- Partials      119      120       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@developerkunal
Copy link
Contributor

Hi @ErwinSteffens,

I’ve pushed some test cases and a few changes — feel free to review and let me know if anything needs to be reverted or adjusted. I intended to open a PR, but it looks like the changes were pushed directly by mistake.

Apologies for the mix-up!

@developerkunal developerkunal force-pushed the client-creds-private-key-jwt branch from 8584b44 to 636d182 Compare April 6, 2025 16:48
@developerkunal developerkunal changed the title Add client credentials Private Key JWT auth for management API Add Private Key JWT support for client credentials in Management API Apr 6, 2025
@developerkunal developerkunal requested a review from Copilot April 6, 2025 16:58
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.

Comments suppressed due to low confidence (1)

internal/client/jwt_token_source.go:111

  • [nitpick] Consider enhancing the error message to include a list of supported algorithms for clearer guidance, e.g., by appending the supported options to the message.
return "", fmt.Errorf("unsupported client assertion algorithm %q", alg)

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants