loadCustomProvider loads a custom OAuth or OIDC provider from the database identifier should be the full provider name with 'custom:' prefix (e.g., 'custom:github-enterprise')
(ctx context.Context, db *storage.Connection, identifier string, scopes string)
| 687 | // loadCustomProvider loads a custom OAuth or OIDC provider from the database |
| 688 | // identifier should be the full provider name with 'custom:' prefix (e.g., 'custom:github-enterprise') |
| 689 | func (a *API) loadCustomProvider(ctx context.Context, db *storage.Connection, identifier string, scopes string) (provider.Provider, conf.OAuthProviderConfiguration, error) { |
| 690 | config := a.config |
| 691 | var pConfig conf.OAuthProviderConfiguration |
| 692 | |
| 693 | redirectURL := strings.TrimRight(config.API.ExternalURL, "/") + "/callback" |
| 694 | |
| 695 | // Parse scopes (space-separated per RFC 6749) |
| 696 | var scopeList []string |
| 697 | if scopes != "" { |
| 698 | scopeList = strings.Fields(scopes) |
| 699 | } |
| 700 | |
| 701 | // Find the custom provider by identifier (which now includes 'custom:' prefix) |
| 702 | customProvider, err := models.FindCustomOAuthProviderByIdentifier(db, identifier) |
| 703 | if err != nil { |
| 704 | if models.IsNotFoundError(err) { |
| 705 | return nil, pConfig, fmt.Errorf("custom provider %s not found", identifier) |
| 706 | } |
| 707 | return nil, pConfig, fmt.Errorf("error finding custom provider: %w", err) |
| 708 | } |
| 709 | |
| 710 | // Check if provider is enabled |
| 711 | if !customProvider.Enabled { |
| 712 | return nil, pConfig, fmt.Errorf("custom provider %s is disabled", identifier) |
| 713 | } |
| 714 | |
| 715 | // Use provider scopes if not overridden |
| 716 | if len(scopeList) == 0 { |
| 717 | scopeList = customProvider.Scopes |
| 718 | } |
| 719 | |
| 720 | // Decrypt client secret for runtime use |
| 721 | clientSecret, err := customProvider.GetClientSecret(config.Security.DBEncryption) |
| 722 | if err != nil { |
| 723 | return nil, pConfig, fmt.Errorf("error decrypting client secret for provider %s: %w", identifier, err) |
| 724 | } |
| 725 | |
| 726 | // Handle based on provider type |
| 727 | if customProvider.IsOAuth2() { |
| 728 | // OAuth2 provider |
| 729 | if customProvider.AuthorizationURL == nil || customProvider.TokenURL == nil || customProvider.UserinfoURL == nil { |
| 730 | return nil, pConfig, fmt.Errorf("OAuth2 provider %s missing required endpoints", identifier) |
| 731 | } |
| 732 | |
| 733 | // Create custom OAuth provider instance |
| 734 | p := provider.NewCustomOAuthProvider( |
| 735 | customProvider.ClientID, |
| 736 | clientSecret, |
| 737 | *customProvider.AuthorizationURL, |
| 738 | *customProvider.TokenURL, |
| 739 | *customProvider.UserinfoURL, |
| 740 | redirectURL, |
| 741 | scopeList, |
| 742 | customProvider.PKCEEnabled, |
| 743 | customProvider.AcceptableClientIDs, |
| 744 | customProvider.AttributeMapping, |
| 745 | customProvider.AuthorizationParams, |
| 746 | customProvider.CustomClaimsAllowlist, |
no test coverage detected