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}