federatedauth

package
v0.1.35 Latest Latest
Warning

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

Go to latest
Published: Jul 3, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package federatedauth owns provider-mediated authentication orchestration — OAuth and SAML callback handlers plus account-linking helpers — that build on the account model in accounts/ and the session/middleware machinery in httpauth/.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AuthUserStore

type AuthUserStore interface {
	accounts.UserStore
	accounts.IdentityStore
	accounts.ChannelStore

	// EnsureAuthUser orchestrates user creation/lookup across stores.
	// This is the main entry point for OAuth and local authentication.
	EnsureAuthUser(authtype string, provider string, token *oauth2.Token, userInfo map[string]any) (accounts.User, error)
}

AuthUserStore combines the store interfaces needed for federated-auth callbacks plus the EnsureAuthUser orchestration that turns provider userInfo into an accounts.User.

type EnsureAuthUserConfig

type EnsureAuthUserConfig struct {
	UserStore     accounts.UserStore
	IdentityStore accounts.IdentityStore
	ChannelStore  accounts.ChannelStore
	UsernameStore accounts.UsernameStore
}

EnsureAuthUserConfig holds configuration for NewEnsureAuthUserFunc.

type EnsureAuthUserFunc

type EnsureAuthUserFunc func(authtype string, provider string, token any, userInfo map[string]any) (accounts.User, error)

EnsureAuthUserFunc handles user creation/lookup for both OAuth and local authentication with channel linking support.

func NewEnsureAuthUserFunc

func NewEnsureAuthUserFunc(config EnsureAuthUserConfig) EnsureAuthUserFunc

NewEnsureAuthUserFunc creates a function that handles user creation/lookup for both OAuth and local authentication with channel linking support.

type OAuthBridge

type OAuthBridge struct {
	OneAuth   *httpauth.OneAuth
	UserStore AuthUserStore
}

OAuthBridge wires httpauth's session/cookie machinery to the federated-auth callback flow. Construct one per OneAuth instance and hand its methods to your OAuth provider handlers.

Example:

bridge := federatedauth.NewOAuthBridge(oneauth, authUserStore)
oneauth.AddAuth("/google", oa2.NewGoogleOAuth2(
    clientID, clientSecret, callbackURL,
    bridge.SaveUserAndRedirect,
).Handler())

func NewOAuthBridge

func NewOAuthBridge(oneAuth *httpauth.OneAuth, userStore AuthUserStore) *OAuthBridge

NewOAuthBridge creates an OAuthBridge that callbacks dispatch through.

func (*OAuthBridge) GetLinkingUserID

func (b *OAuthBridge) GetLinkingUserID(r *http.Request) string

GetLinkingUserID retrieves and clears the linking user ID from session. Call this in your OAuth callback to detect linking mode.

func (*OAuthBridge) HandleLinkOAuthCallback

func (b *OAuthBridge) HandleLinkOAuthCallback(linkingUserID, provider string, userInfo map[string]any, w http.ResponseWriter, r *http.Request)

HandleLinkOAuthCallback links an OAuth provider channel onto an existing, already-logged-in user.

Who Calls This

This is called by OAuth providers after the user authorizes linking. The flow is:

  1. Local-only user visits profile, clicks "Link Google Account"
  2. App stores user ID in session as "linkingUserID" (via b.StartLinkOAuth)
  3. App redirects to Google OAuth with special state
  4. Google redirects back to /auth/google/callback
  5. OAuth callback sees "linkingUserID" in session (via b.GetLinkingUserID)
  6. Instead of normal login, calls this handler to link the account

How to Set Up

Modify your OAuth callback to detect linking mode:

func googleCallback(w http.ResponseWriter, r *http.Request) {
    // ... exchange code for token, get userInfo ...

    linkingUserID := bridge.GetLinkingUserID(r)
    if linkingUserID != "" {
        bridge.HandleLinkOAuthCallback(linkingUserID, "google", userInfo, w, r)
        return
    }

    bridge.SaveUserAndRedirect("oauth", "google", token, userInfo, w, r)
}

What It Does

  1. Verifies the OAuth email matches the user's existing email identity
  2. Creates OAuth channel for the provider
  3. Updates user profile["channels"] to include the new provider
  4. Redirects to callback URL

Security

The OAuth email MUST match the user's existing email to prevent account hijacking. Users cannot link to a different email address.

func (*OAuthBridge) SaveUserAndRedirect

func (b *OAuthBridge) SaveUserAndRedirect(authtype, provider string, token *oauth2.Token, userInfo map[string]any, w http.ResponseWriter, r *http.Request)

SaveUserAndRedirect is called by an OAuth callback handler with the auth token and user info after a successful auth flow and redirect.

Here is our opportunity to:

  1. Create a userId that is unique to our system based on userInfo
  2. Set the right session cookies from this

func (*OAuthBridge) StartLinkOAuth

func (b *OAuthBridge) StartLinkOAuth(r *http.Request, userID string)

StartLinkOAuth initiates OAuth account linking by storing the user ID in session. Call this from your "Link [Provider] Account" button handler.

Example:

func handleLinkGoogle(w http.ResponseWriter, r *http.Request) {
    userID := getLoggedInUserID(r)
    bridge.StartLinkOAuth(r, userID)
    http.Redirect(w, r, "/auth/google/", http.StatusFound)
}

Jump to

Keyboard shortcuts

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