Files
tinyauth/cmd/tinyauth/create_oidc_client.go
T
2026-07-02 17:49:56 +03:00

115 lines
3.1 KiB
Go

package main
import (
"errors"
"fmt"
"regexp"
"strings"
"github.com/google/uuid"
"github.com/tinyauthapp/paerser/cli"
"github.com/tinyauthapp/tinyauth/internal/model"
"github.com/tinyauthapp/tinyauth/internal/utils"
"gopkg.in/yaml.v3"
)
func createOidcClientCmd() *cli.Command {
return &cli.Command{
Name: "create",
Description: "Create a new OIDC Client",
Configuration: nil,
Resources: nil,
AllowArg: true,
Run: func(args []string) error {
if len(args) == 0 {
return errors.New("client name is required. use tinyauth oidc create <name>")
}
clientName := args[0]
match, err := regexp.MatchString("^[a-zA-Z0-9-]*$", clientName)
if !match || err != nil {
return errors.New("client name can only contain alphanumeric characters and hyphens")
}
uuid := uuid.New()
clientId := uuid.String()
clientSecret := "ta-" + utils.GenerateString(61)
uclientName := strings.ToUpper(clientName)
lclientName := strings.ToLower(clientName)
buf := strings.Builder{}
// header
fmt.Fprintf(&buf, "Created '%s' OIDC client.\n\n", clientName)
// credentials
fmt.Fprintf(&buf, "Credentials:\n\n")
fmt.Fprintf(&buf, "Client Name: %s\n", clientName)
fmt.Fprintf(&buf, "Client ID: %s\n", clientId)
fmt.Fprintf(&buf, "Client Secret: %s\n\n", clientSecret)
// end variables
fmt.Fprintf(&buf, "Environment variables:\n\n")
renderToBuf(&buf, map[string]string{
fmt.Sprintf("TINYAUTH_OIDC_CLIENTS_%s_CLIENTID", uclientName): clientId,
fmt.Sprintf("TINYAUTH_OIDC_CLIENTS_%s_CLIENTSECRET", uclientName): clientSecret,
fmt.Sprintf("TINYAUTH_OIDC_CLIENTS_%s_NAME", uclientName): utils.Capitalize(lclientName),
}, "=")
fmt.Fprintf(&buf, "\n")
// cli flags
fmt.Fprintf(&buf, "CLI flags:\n\n")
renderToBuf(&buf, map[string]string{
fmt.Sprintf("--oidc-clients-%s-clientid", lclientName): clientId,
fmt.Sprintf("--oidc-clients-%s-clientsecret", lclientName): clientSecret,
fmt.Sprintf("--oidc-clients-%s-name", lclientName): utils.Capitalize(lclientName),
}, "=")
fmt.Fprintf(&buf, "\n")
// yaml config
fmt.Fprintf(&buf, "YAML config:\n\n")
yout, err := yaml.Marshal(&model.OIDCConfig{
Clients: map[string]model.OIDCClientConfig{
lclientName: {
ClientID: clientId,
ClientSecret: clientSecret,
Name: utils.Capitalize(lclientName),
},
},
})
if err != nil {
return fmt.Errorf("failed to marshal yaml: %w", err)
}
for l := range strings.SplitSeq(string(yout), "\n") {
if l == "" {
continue
}
lp := strings.SplitN(l, ":", 2)
buf.WriteString(redStyle.Render(lp[0]))
buf.WriteString(grayStyle.Render(":"))
if len(lp) == 2 {
buf.WriteString("")
buf.WriteString(greenStyle.Render(lp[1]))
}
buf.WriteString("\n")
}
buf.WriteString("\n")
// footer
fmt.Fprintln(&buf, "You can use any of the above options to configure your OIDC client. Make sure to save these credentials as there is no way to regenerate them.")
// print
out := buf.String()
fmt.Print(out)
return nil
},
}
}