1package cmd
2
3import (
4 "fmt"
5 "time"
6
7 "github.com/charmbracelet/soft-serve/pkg/config"
8 "github.com/charmbracelet/soft-serve/pkg/jwk"
9 "github.com/charmbracelet/soft-serve/pkg/proto"
10 "github.com/golang-jwt/jwt/v5"
11 "github.com/spf13/cobra"
12)
13
14// JWTCommand returns a command that generates a JSON Web Token.
15func JWTCommand() *cobra.Command {
16 cmd := &cobra.Command{
17 Use: "jwt [repository1 repository2...]",
18 Short: "Generate a JSON Web Token",
19 Args: cobra.MinimumNArgs(0),
20 RunE: func(cmd *cobra.Command, args []string) error {
21 ctx := cmd.Context()
22 cfg := config.FromContext(ctx)
23 kp, err := jwk.NewPair(cfg)
24 if err != nil {
25 return err //nolint:wrapcheck
26 }
27
28 user := proto.UserFromContext(ctx)
29 if user == nil {
30 return proto.ErrUserNotFound
31 }
32
33 now := time.Now()
34 expiresAt := now.Add(time.Hour)
35 claims := jwt.RegisteredClaims{
36 Subject: fmt.Sprintf("%s#%d", user.Username(), user.ID()),
37 ExpiresAt: jwt.NewNumericDate(expiresAt), // expire in an hour
38 NotBefore: jwt.NewNumericDate(now),
39 IssuedAt: jwt.NewNumericDate(now),
40 Issuer: cfg.HTTP.PublicURL,
41 Audience: args,
42 }
43
44 token := jwt.NewWithClaims(jwk.SigningMethod, claims)
45 token.Header["kid"] = kp.JWK().KeyID
46 j, err := token.SignedString(kp.PrivateKey())
47 if err != nil {
48 return err //nolint:wrapcheck
49 }
50
51 cmd.Println(j)
52 return nil
53 },
54 }
55
56 return cmd
57}