jwt.go

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