federation

package
v1.0.20 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 26, 2025 License: MIT Imports: 15 Imported by: 0

Documentation

Index

Constants

View Source
const (
	AppleAuthURL  = "https://appleid.apple.com/auth/authorize"
	AppleTokenURL = "https://appleid.apple.com/auth/token"
)

Variables

View Source
var (
	ErrProviderNotFound      = errors.New("provider not found or not enabled")
	ErrInvalidAuthState      = errors.New("invalid auth state parameter")
	ErrExchangeCodeFailed    = errors.New("failed to exchange authorization code for token")
	ErrFetchUserInfoFailed   = errors.New("failed to fetch user info from provider")
	ErrProviderMisconfigured = errors.New("provider is misconfigured")
	ErrAccountAlreadyLinked  = errors.New("this external account is already linked to another user")
	ErrLocalUserLinkConflict = errors.New("this local user is already linked to an account from this provider")
)
View Source
var (
	GithubUserInfoEndpoint   = "https://api.github.com/user"
	GithubUserEmailsEndpoint = "https://api.github.com/user/emails"
)
View Source
var FacebookUserInfoEndpoint = "https://graph.facebook.com/me?fields=id,name,first_name,last_name,email,picture"

Facebook's Graph API endpoint for user info. The fields parameter specifies what data to retrieve.

View Source
var GoogleUserInfoEndpoint = "https://www.googleapis.com/oauth2/v3/userinfo"

Functions

This section is empty.

Types

type AppleProvider

type AppleProvider struct {
	*BaseProvider
}

AppleProvider implements the OAuth2Provider interface for Sign in with Apple.

func NewAppleProvider

func NewAppleProvider(idpConfig *domain.IdentityProvider) (*AppleProvider, error)

NewAppleProvider creates a new AppleProvider. The idpConfig.OIDCClientSecret for Apple is expected to be a pre-generated client secret JWT.

func (*AppleProvider) ExchangeCode

func (a *AppleProvider) ExchangeCode(ctx context.Context, redirectURL string, code string, opts ...oauth2.AuthCodeOption) (*oauth2.Token, error)

ExchangeCode for Apple. The `user` form parameter may contain name info. The primary user info comes from the ID token.

func (*AppleProvider) FetchUserInfo

func (a *AppleProvider) FetchUserInfo(ctx context.Context, token *oauth2.Token) (*ExternalUserInfo, error)

FetchUserInfo for Apple primarily parses the ID token. Apple does not have a separate userinfo endpoint that returns all details like other providers. Name and email are only guaranteed in the first authorization's ID token. The `user` POST parameter during the /auth/authorize call might also contain name info if requested with scope=name. This information should ideally be captured and stored locally when the user first signs up.

func (*AppleProvider) GetAuthCodeURL

func (a *AppleProvider) GetAuthCodeURL(state, redirectURL string, opts ...oauth2.AuthCodeOption) (string, error)

GetAuthCodeURL for Apple needs to include response_mode="form_post" as Apple expects it.

func (*AppleProvider) GetOAuth2Config

func (a *AppleProvider) GetOAuth2Config(redirectURL string) (*oauth2.Config, error)

GetOAuth2Config overrides BaseProvider's method to use Apple's specific endpoints and handles the client_secret_post authentication method if the secret is a JWT.

type BaseProvider

type BaseProvider struct {
	Config *domain.IdentityProvider // Holds the configuration loaded from the database
}

BaseProvider provides a common structure and partial implementation for OAuth2Provider. Specific providers can embed this and override methods as needed.

func NewBaseProvider

func NewBaseProvider(idpConfig *domain.IdentityProvider) *BaseProvider

func (*BaseProvider) ExchangeCode

func (b *BaseProvider) ExchangeCode(ctx context.Context, redirectURL string, code string, opts ...oauth2.AuthCodeOption) (*oauth2.Token, error)

func (*BaseProvider) FetchUserInfo

func (b *BaseProvider) FetchUserInfo(ctx context.Context, token *oauth2.Token) (*ExternalUserInfo, error)

FetchUserInfo is a placeholder and MUST be implemented by each specific provider as the user info endpoint and response structure varies.

func (*BaseProvider) GetAuthCodeURL

func (b *BaseProvider) GetAuthCodeURL(state, redirectURL string, opts ...oauth2.AuthCodeOption) (string, error)

func (*BaseProvider) GetHttpClient

func (b *BaseProvider) GetHttpClient(ctx context.Context, token *oauth2.Token) *http.Client

func (*BaseProvider) GetOAuth2Config

func (b *BaseProvider) GetOAuth2Config(redirectURL string) (*oauth2.Config, error)

GetOAuth2Config constructs an oauth2.Config from the stored IdP configuration. This method can be overridden if a provider has non-standard endpoint discovery.

func (*BaseProvider) GetType

func (b *BaseProvider) GetType() domain.IdPType

func (*BaseProvider) Name

func (b *BaseProvider) Name() string

type ExternalUserInfo

type ExternalUserInfo struct {
	ProviderUserID string // Unique ID of the user within the external provider (e.g., Google's 'sub')
	Email          string
	FirstName      string
	LastName       string
	Username       string // Or preferred username
	PictureURL     string
	RawData        map[string]interface{} // Raw user data from the provider
}

ExternalUserInfo holds standardized user information retrieved from an external OAuth2 provider.

type FacebookProvider

type FacebookProvider struct {
	*BaseProvider
}

FacebookProvider implements the OAuth2Provider interface for Facebook.

func NewFacebookProvider

func NewFacebookProvider(idpConfig *domain.IdentityProvider) (*FacebookProvider, error)

NewFacebookProvider creates a new FacebookProvider.

func (*FacebookProvider) FetchUserInfo

func (f *FacebookProvider) FetchUserInfo(ctx context.Context, token *oauth2.Token) (*ExternalUserInfo, error)

FetchUserInfo overrides BaseProvider's method to fetch user information from Facebook's Graph API.

func (*FacebookProvider) GetOAuth2Config

func (f *FacebookProvider) GetOAuth2Config(redirectURL string) (*oauth2.Config, error)

GetOAuth2Config overrides BaseProvider's method to use Facebook's endpoints.

type GitHubProvider

type GitHubProvider struct {
	*BaseProvider
}

GitHubProvider implements the OAuth2Provider interface for GitHub.

func NewGitHubProvider

func NewGitHubProvider(idpConfig *domain.IdentityProvider) (*GitHubProvider, error)

NewGitHubProvider creates a new GitHubProvider.

func (*GitHubProvider) FetchUserInfo

func (g *GitHubProvider) FetchUserInfo(ctx context.Context, token *oauth2.Token) (*ExternalUserInfo, error)

FetchUserInfo overrides BaseProvider's method to fetch user information from GitHub. GitHub requires two calls: one for user profile, another for primary email if `user:email` scope is granted.

func (*GitHubProvider) GetOAuth2Config

func (g *GitHubProvider) GetOAuth2Config(redirectURL string) (*oauth2.Config, error)

GetOAuth2Config overrides BaseProvider's method to use GitHub's well-known endpoints.

type GoogleProvider

type GoogleProvider struct {
	*BaseProvider
}

GoogleProvider implements the OAuth2Provider interface for Google.

func NewGoogleProvider

func NewGoogleProvider(idpConfig *domain.IdentityProvider) (*GoogleProvider, error)

NewGoogleProvider creates a new GoogleProvider. It expects an IdP configuration that has been populated with Google's specific ClientID, ClientSecret, and desired Scopes.

func (*GoogleProvider) FetchUserInfo

func (g *GoogleProvider) FetchUserInfo(ctx context.Context, token *oauth2.Token) (*ExternalUserInfo, error)

FetchUserInfo overrides BaseProvider's method to fetch user information from Google.

func (*GoogleProvider) GetOAuth2Config

func (g *GoogleProvider) GetOAuth2Config(redirectURL string) (*oauth2.Config, error)

GetOAuth2Config overrides BaseProvider's method to use Google's well-known endpoints.

type OAuth2Provider

type OAuth2Provider interface {
	// Name returns the unique identifier for the provider (e.g., "google", "facebook").
	Name() string

	// GetType returns the type of the provider (e.g. "OIDC").
	GetType() domain.IdPType

	// GetOAuth2Config returns the oauth2.Config struct, initialized with the provider's
	// client ID, client secret, redirect URL, scopes, and auth/token endpoints.
	// The redirectURL parameter is the one configured in our system for this provider.
	GetOAuth2Config(redirectURL string) (*oauth2.Config, error)

	// GetAuthCodeURL generates the authorization URL the user should be redirected to.
	// It takes a state parameter for CSRF protection and the system's redirect URL.
	// It may also accept additional auth code options (e.g., PKCE parameters, nonce).
	GetAuthCodeURL(state, redirectURL string, opts ...oauth2.AuthCodeOption) (string, error)

	// ExchangeCode exchanges an authorization code for an OAuth2 token.
	ExchangeCode(ctx context.Context, redirectURL string, code string, opts ...oauth2.AuthCodeOption) (*oauth2.Token, error)

	// FetchUserInfo uses an access token to retrieve user information from the provider.
	// It returns a standardized ExternalUserInfo struct.
	FetchUserInfo(ctx context.Context, token *oauth2.Token) (*ExternalUserInfo, error)

	// GetHttpClient returns an *http.Client that can be used to make requests
	// to the provider's API, authenticated with the given token.
	GetHttpClient(ctx context.Context, token *oauth2.Token) *http.Client
}

OAuth2Provider defines the interface for an external OAuth2 identity provider. Implementations of this interface will handle provider-specific details.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service handles the core logic for OAuth2 federation.

func NewService

func NewService(idpRepo domain.IdPRepository, defaultRedirectURL string) *Service

NewService creates a new federation Service. defaultRedirectURL is the base URL to which providers should redirect back, e.g., "https://sso.example.com/federation/callback". The provider name will be appended.

func (*Service) GenerateAuthState

func (s *Service) GenerateAuthState() (string, error)

GenerateAuthState generates a unique, unguessable string for the state parameter.

func (*Service) GetAuthorizationURL

func (s *Service) GetAuthorizationURL(ctx context.Context, providerName string, state string, authCodeOptions ...oauth2.AuthCodeOption) (string, error)

GetAuthorizationURL constructs the URL to redirect the user to for authentication with the external provider.

func (*Service) GetProvider

func (s *Service) GetProvider(ctx context.Context, providerName string) (OAuth2Provider, error)

GetProvider retrieves and initializes a provider by its name. It first checks the registry, then tries to load and construct it from IdPRepository. This method needs to be expanded to instantiate specific provider types (Google, Facebook, etc.) based on the IdP configuration. For now, it's a placeholder for fetching from registry. A more dynamic approach would involve a factory pattern.

func (*Service) GetRedirectURLForProvider

func (s *Service) GetRedirectURLForProvider(providerName string) string

GetRedirectURLForProvider constructs the specific redirect URL for a given provider. E.g., https://sso.example.com/federation/callback/google

func (*Service) HandleCallback

func (s *Service) HandleCallback(
	ctx context.Context,
	providerName string,
	queryState string,
	sessionState string,
	code string,
	authCodeOptions ...oauth2.AuthCodeOption,
) (*ExternalUserInfo, *oauth2.Token, error)

HandleCallback processes the callback from the external provider. It exchanges the authorization code for a token and fetches user information. The `queryState` is the state received in the callback URL. The `sessionState` is the state previously stored (e.g., in a cookie) to prevent CSRF. `code` is the authorization code from the callback.

func (*Service) RegisterProvider

func (s *Service) RegisterProvider(provider OAuth2Provider)

RegisterProvider allows specific provider implementations to be added to the service. This is more of a dependency injection pattern. Alternatively, providers can be constructed on-demand.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL