Documentation
¶
Index ¶
- Constants
- Variables
- type AppleProvider
- func (a *AppleProvider) ExchangeCode(ctx context.Context, redirectURL string, code string, ...) (*oauth2.Token, error)
- func (a *AppleProvider) FetchUserInfo(ctx context.Context, token *oauth2.Token) (*ExternalUserInfo, error)
- func (a *AppleProvider) GetAuthCodeURL(state, redirectURL string, opts ...oauth2.AuthCodeOption) (string, error)
- func (a *AppleProvider) GetOAuth2Config(redirectURL string) (*oauth2.Config, error)
- type BaseProvider
- func (b *BaseProvider) ExchangeCode(ctx context.Context, redirectURL string, code string, ...) (*oauth2.Token, error)
- func (b *BaseProvider) FetchUserInfo(ctx context.Context, token *oauth2.Token) (*ExternalUserInfo, error)
- func (b *BaseProvider) GetAuthCodeURL(state, redirectURL string, opts ...oauth2.AuthCodeOption) (string, error)
- func (b *BaseProvider) GetHttpClient(ctx context.Context, token *oauth2.Token) *http.Client
- func (b *BaseProvider) GetOAuth2Config(redirectURL string) (*oauth2.Config, error)
- func (b *BaseProvider) GetType() domain.IdPType
- func (b *BaseProvider) Name() string
- type ExternalUserInfo
- type FacebookProvider
- type GitHubProvider
- type GoogleProvider
- type OAuth2Provider
- type Service
- func (s *Service) GenerateAuthState() (string, error)
- func (s *Service) GetAuthorizationURL(ctx context.Context, providerName string, state string, ...) (string, error)
- func (s *Service) GetProvider(ctx context.Context, providerName string) (OAuth2Provider, error)
- func (s *Service) GetRedirectURLForProvider(providerName string) string
- func (s *Service) HandleCallback(ctx context.Context, providerName string, queryState string, ...) (*ExternalUserInfo, *oauth2.Token, error)
- func (s *Service) RegisterProvider(provider OAuth2Provider)
Constants ¶
const ( AppleAuthURL = "https://appleid.apple.com/auth/authorize" AppleTokenURL = "https://appleid.apple.com/auth/token" )
Variables ¶
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") )
var ( GithubUserInfoEndpoint = "https://api.github.com/user" GithubUserEmailsEndpoint = "https://api.github.com/user/emails" )
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.
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 (*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 ¶
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 ¶
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 ¶
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.