Guide for integrating authhub (third-party OAuth login) into downstream GoBase applications, covering recommended structure, config, route registration, callback handling, user linking, provider examples, and responsibility boundaries with GoBase core auth.
Library:
github.com/simp-lee/authhubScope: Downstream application code only — GoBase framework is not modified. Load also:gobase-architecture,gobase-auth-extension
AuthHub provides third-party OAuth login (GitHub, Google, etc.) as a standalone library. It is not a built-in GoBase capability — integration happens entirely in the downstream application that imports GoBase.
This skill guides AI agents through adding authhub support to a GoBase-based application while maintaining clean separation from GoBase's core auth system (JWT + bcrypt password login).
| Non-Goal |
|---|
| Rationale |
|---|
Modify GoBase core (github.com/simp-lee/gobase) | OAuth is application-level, not framework-level |
Add OAuth dependencies to GoBase's go.mod | Keeps the starter kit dependency tree minimal |
| Replace GoBase's JWT auth system | authhub complements password login; it does not supersede it |
| Provide a universal OAuth abstraction | authhub handles provider specifics; the downstream app only wires it |
| Implement account merging or multi-provider linking UI | These are product-level decisions left to the downstream application |
┌─────────────────────────────────────────────────┐
│ Downstream Application │
│ │
│ ┌──────────────┐ ┌───────────────────────┐ │
│ │ authhub │ │ GoBase auth module │ │
│ │ module │ │ (JWT, login, register)│ │
│ │ │ │ │ │
│ │ OAuth flow │───▶│ GenerateToken() │ │
│ │ Provider cfg │ │ User lookup/create │ │
│ │ Callback │ │ │ │
│ └──────────────┘ └───────────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────────────────────────────────┐ │
│ │ domain.User + OAuth identity storage │ │
│ └──────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
Add authhub as a new module under internal/module/ in the downstream application:
internal/module/authhub/
├── dto.go # OAuth-related request/response structs
├── handler.go # HTTP handlers: redirect + callback endpoints
├── handler_test.go
├── module.go # Implements app.Module, registers routes
├── module_test.go
├── provider.go # Provider configuration and authhub client setup
├── provider_test.go
├── repository.go # OAuth identity persistence (user_oauth_identities table)
├── repository_test.go
├── service.go # OAuth flow logic, user find-or-create
└── service_test.go
Additionally, extend the domain layer:
internal/domain/
├── user.go # Existing — no changes required to GoBase's User struct
└── oauth_identity.go # New — OAuthIdentity entity + OAuthIdentityRepository interface
Create internal/domain/oauth_identity.go in the downstream app:
package domain
import "context"
// OAuthIdentity links an external OAuth provider account to a local user.
type OAuthIdentity struct {
BaseModel
UserID uint `gorm:"not null;index:idx_oauth_user" json:"user_id"`
Provider string `gorm:"size:50;not null;uniqueIndex:idx_oauth_provider_subject" json:"provider"`
Subject string `gorm:"size:255;not null;uniqueIndex:idx_oauth_provider_subject" json:"subject"`
Email string `gorm:"size:255" json:"email,omitempty"`
DisplayName string `gorm:"size:200" json:"display_name,omitempty"`
}
// OAuthIdentityRepository defines data access for OAuth identities.
type OAuthIdentityRepository interface {
Create(ctx context.Context, identity *OAuthIdentity) error
GetByProviderAndSubject(ctx context.Context, provider, subject string) (*OAuthIdentity, error)
ListByUserID(ctx context.Context, userID uint) ([]OAuthIdentity, error)
Delete(ctx context.Context, id uint) error
}
Key rules:
Provider + Subject form a unique composite index — one external account maps to exactly one local user.UserID references domain.User.ID — the existing GoBase user table.User struct; the link lives in the separate oauth_identities table.Add OAuth provider settings to the downstream app's config.yaml: