feat: add AuthProvider model and identity provider presets
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"gitea.hostxtra.co.uk/mrhid6/vantage/server/internal/models"
|
||||
)
|
||||
|
||||
// Preset describes one well-known identity provider.
|
||||
//
|
||||
// This is a Go table rather than a collection on purpose: adding a preset is a
|
||||
// commit and a review, not a row somebody typed into production.
|
||||
type Preset struct {
|
||||
ID string `json:"id"`
|
||||
Label string `json:"label"` // shown in the add-provider picker
|
||||
Kind string `json:"kind"` // models.KindOIDC | models.KindOAuth2
|
||||
IssuerFormat string `json:"-"` // %s is replaced by InputValue; empty means no issuer
|
||||
InputLabel string `json:"input_label"` // empty means the preset asks for nothing
|
||||
InputHint string `json:"input_hint"`
|
||||
Scopes []string `json:"-"`
|
||||
}
|
||||
|
||||
var presets = []Preset{
|
||||
{
|
||||
ID: "entra",
|
||||
Label: "Microsoft Entra ID",
|
||||
Kind: models.KindOIDC,
|
||||
IssuerFormat: "https://login.microsoftonline.com/%s/v2.0",
|
||||
InputLabel: "Directory (tenant) ID",
|
||||
InputHint: "Found in Entra under Overview. A UUID, not your domain name.",
|
||||
Scopes: []string{"openid", "profile", "email"},
|
||||
},
|
||||
{
|
||||
ID: "google",
|
||||
Label: "Google Workspace",
|
||||
Kind: models.KindOIDC,
|
||||
IssuerFormat: "https://accounts.google.com",
|
||||
Scopes: []string{"openid", "profile", "email"},
|
||||
},
|
||||
{
|
||||
ID: "okta",
|
||||
Label: "Okta",
|
||||
Kind: models.KindOIDC,
|
||||
IssuerFormat: "https://%s/oauth2/default",
|
||||
InputLabel: "Okta org domain",
|
||||
InputHint: "e.g. acme.okta.com — no scheme, no trailing slash.",
|
||||
Scopes: []string{"openid", "profile", "email"},
|
||||
},
|
||||
{
|
||||
ID: "github",
|
||||
Label: "GitHub",
|
||||
Kind: models.KindOAuth2,
|
||||
Scopes: []string{"read:user", "user:email"},
|
||||
},
|
||||
{
|
||||
ID: "",
|
||||
Label: "Other (OpenID Connect)",
|
||||
Kind: models.KindOIDC,
|
||||
IssuerFormat: "%s",
|
||||
InputLabel: "Issuer URL",
|
||||
InputHint: "The discovery base, e.g. https://id.example.com/realms/main",
|
||||
Scopes: []string{"openid", "profile", "email"},
|
||||
},
|
||||
}
|
||||
|
||||
// Presets returns the table for the settings UI to render a picker from.
|
||||
func Presets() []Preset {
|
||||
out := make([]Preset, len(presets))
|
||||
copy(out, presets)
|
||||
return out
|
||||
}
|
||||
|
||||
func PresetByID(id string) (Preset, bool) {
|
||||
for _, p := range presets {
|
||||
if p.ID == id {
|
||||
return p, true
|
||||
}
|
||||
}
|
||||
return Preset{}, false
|
||||
}
|
||||
|
||||
// ExpandIssuer turns what the customer typed into the issuer URL that gets
|
||||
// stored. The stored value is always fully resolved, so nothing downstream has
|
||||
// to know a preset was involved.
|
||||
func ExpandIssuer(presetID, input string) (string, error) {
|
||||
p, ok := PresetByID(presetID)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("unknown provider preset %q", presetID)
|
||||
}
|
||||
if p.IssuerFormat == "" {
|
||||
return "", nil // OAuth2 providers have no issuer
|
||||
}
|
||||
if !strings.Contains(p.IssuerFormat, "%s") {
|
||||
return p.IssuerFormat, nil // fixed issuer, input ignored
|
||||
}
|
||||
input = strings.TrimSpace(strings.TrimSuffix(input, "/"))
|
||||
if input == "" {
|
||||
return "", fmt.Errorf("%s is required", p.InputLabel)
|
||||
}
|
||||
return fmt.Sprintf(p.IssuerFormat, input), nil
|
||||
}
|
||||
|
||||
func DefaultScopes(presetID string) []string {
|
||||
p, ok := PresetByID(presetID)
|
||||
if !ok {
|
||||
return []string{"openid", "profile", "email"}
|
||||
}
|
||||
out := make([]string, len(p.Scopes))
|
||||
copy(out, p.Scopes)
|
||||
return out
|
||||
}
|
||||
|
||||
func KindFor(presetID string) string {
|
||||
if p, ok := PresetByID(presetID); ok {
|
||||
return p.Kind
|
||||
}
|
||||
return models.KindOIDC
|
||||
}
|
||||
Reference in New Issue
Block a user