• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mindersec / minder / 25334664832

04 May 2026 05:58PM UTC coverage: 60.442% (-0.1%) from 60.56%
25334664832

push

github

web-flow
Generalize identity provider and implement OIDC discovery (#6265)

* feat(auth): generalize identity provider and implement OIDC discovery

This commit decouples Minder from Keycloak-specific paths by:
- Implementing OIDC discovery for identity server configuration.
- Defining the IdentityManager interface for administrative operations.
- Refactoring event synchronization and user management to use the new interface.
- Removing legacy Keycloak-specific configuration helpers.
- Updating tests to use the generalized IdentityManager mock.

* chore(auth): fix linting and unit test regressions in identity refactor

- Fix duplicate DeleteUser call in handlers_user.go
- Resolve linting issues (unused receivers, missing docs) in interface.go
- Update tests to properly inject MockIdentityManager

* chore(auth): fix linting and add missing unit/integration tests

* refactor(auth): address PR maintainer feedback for IdentityProviders

- Use zitadel/oidc generic client for openid configuration discovery
- OIDC issuer claim matches the discovered client issuer output
- Add missing GitHub IDs clarification
- Include TODOs about unused methods for tracking

* fix(auth): address additional code review feedback

- Fix strings.Contains on ErrNotFound
- Export auth.ErrNotFound
- Restore removed TODO in token handler
- Remove noop test to exclude from coverage as requested
- Discard unintentional metrics/version test commits
- Remove obsolete httptest.NewServer loops

* feat: Add ResolveFederated to auth interface for generic OIDC support

* fix: use issuer_claim for WWW-Authenticate header and accept dual issuer URLs in docker-compose

* style: fix gci formatting in keycloak files

36 of 167 new or added lines in 11 files covered. (21.56%)

1 existing line in 1 file now uncovered.

20396 of 33745 relevant lines covered (60.44%)

38.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.0
/internal/auth/githubactions/githubactions.go
1
// SPDX-FileCopyrightText: Copyright 2025 The Minder Authors
2
// SPDX-License-Identifier: Apache-2.0
3

4
// Package githubactions provides an implementation of the GitHub IdentityProvider.
5
package githubactions
6

7
import (
8
        "context"
9
        "errors"
10
        "net/url"
11
        "strings"
12

13
        "github.com/lestrrat-go/jwx/v2/jwt"
14

15
        "github.com/mindersec/minder/internal/auth"
16
)
17

18
// GitHubActions is an implementation of the auth.IdentityProvider interface.
19
type GitHubActions struct {
20
}
21

22
var _ auth.IdentityProvider = (*GitHubActions)(nil)
23
var _ auth.Resolver = (*GitHubActions)(nil)
24

25
var ghIssuerUrl = url.URL{
26
        Scheme: "https",
27
        Host:   "token.actions.githubusercontent.com",
28
}
29

30
// String implements auth.IdentityProvider.
31
func (*GitHubActions) String() string {
37✔
32
        return "githubactions"
37✔
33
}
37✔
34

35
// URL implements auth.IdentityProvider.
36
func (*GitHubActions) URL() url.URL {
2✔
37
        return ghIssuerUrl
2✔
38
}
2✔
39

40
// Resolve implements auth.IdentityProvider.
41
func (gha *GitHubActions) Resolve(_ context.Context, id string) (*auth.Identity, error) {
2✔
42
        // GitHub Actions subjects look like:
2✔
43
        // repo:evankanderson/actions-id-token-testing:ref:refs/heads/main
2✔
44
        // however, OpenFGA does not allow the "#" or ":" characters in the subject:
2✔
45
        // https://github.com/openfga/openfga/blob/main/pkg/tuple/tuple.go#L34
2✔
46
        return &auth.Identity{
2✔
47
                UserID:    strings.ReplaceAll(id, ":", "+"),
2✔
48
                HumanName: strings.ReplaceAll(id, "+", ":"),
2✔
49
                Provider:  gha,
2✔
50
        }, nil
2✔
51
}
2✔
52

53
// ResolveFederated implements auth.IdentityProvider.
NEW
54
func (*GitHubActions) ResolveFederated(_ context.Context, _, _ string) (*auth.Identity, error) {
×
NEW
55
        return nil, auth.ErrNotFound
×
NEW
56
}
×
57

58
// Validate implements auth.IdentityProvider.
59
func (gha *GitHubActions) Validate(_ context.Context, token jwt.Token) (*auth.Identity, error) {
2✔
60
        expectedUrl := gha.URL()
2✔
61
        if token.Issuer() != expectedUrl.String() {
3✔
62
                return nil, errors.New("token issuer is not the expected issuer")
1✔
63
        }
1✔
64
        return &auth.Identity{
1✔
65
                UserID:    strings.ReplaceAll(token.Subject(), ":", "+"),
1✔
66
                HumanName: token.Subject(),
1✔
67
                Provider:  gha,
1✔
68
        }, nil
1✔
69
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc