Live video on the AT Protocol
at eli/docker-linting 99 lines 2.3 kB view raw
1package oproxy 2 3import ( 4 "crypto/sha256" 5 "encoding/base64" 6 "errors" 7 "fmt" 8 "strings" 9 10 "github.com/AxisCommunications/go-dpop" 11 "github.com/golang-jwt/jwt/v5" 12 "github.com/google/uuid" 13) 14 15func boolPtr(b bool) *bool { 16 return &b 17} 18 19func codeUUID(prefix string) string { 20 uu, err := uuid.NewV7() 21 if err != nil { 22 panic(err) 23 } 24 return fmt.Sprintf("%s-%s", prefix, uu.String()) 25} 26 27var urnPrefix = "urn:ietf:params:oauth:request_uri:" 28 29const UUID_LENGTH = 37 30 31func makeURN(jkt string) string { 32 uu, err := uuid.NewV7() 33 if err != nil { 34 panic(err) 35 } 36 return fmt.Sprintf("%s%s-%s", urnPrefix, uu.String(), jkt) 37} 38 39// urn --> jkt, uu 40func parseURN(urn string) (string, string, error) { 41 if !strings.HasPrefix(urn, urnPrefix) { 42 return "", "", fmt.Errorf("invalid URN: %s", urn) 43 } 44 withoutPrefix := urn[len(urnPrefix):] 45 uu := withoutPrefix[:UUID_LENGTH] 46 suffix := withoutPrefix[UUID_LENGTH:] 47 return suffix, uu, nil 48} 49 50func makeState(jkt string) string { 51 uu, err := uuid.NewV7() 52 if err != nil { 53 panic(err) 54 } 55 return fmt.Sprintf("%s-%s", uu.String(), jkt) 56} 57 58func parseState(state string) (string, string, error) { 59 if len(state) < UUID_LENGTH { 60 return "", "", fmt.Errorf("invalid state: %s", state) 61 } 62 uu := state[:UUID_LENGTH] 63 suffix := state[UUID_LENGTH:] 64 return suffix, uu, nil 65} 66 67func makeNonce() string { 68 uu, err := uuid.NewV7() 69 if err != nil { 70 panic(err) 71 } 72 return fmt.Sprintf("nonce-%s", uu.String()) 73} 74 75// returns jkt, nonce, error 76func getJKT(dpopJWT string) (string, string, error) { 77 var claims dpop.ProofTokenClaims 78 token, err := jwt.ParseWithClaims(dpopJWT, &claims, keyFunc) 79 if err != nil { 80 return "", "", err 81 } 82 jwk, ok := token.Header["jwk"].(map[string]any) 83 if !ok { 84 return "", "", fmt.Errorf("missing jwk in DPoP JWT header") 85 } 86 jwkJSONbytes, err := getThumbprintableJwkJSONbytes(jwk) 87 if err != nil { 88 // keyFunc used with parseWithClaims should ensure that this can not happen but better safe than sorry. 89 return "", "", errors.Join(dpop.ErrInvalidProof, err) 90 } 91 h := sha256.New() 92 _, err = h.Write(jwkJSONbytes) 93 if err != nil { 94 return "", "", errors.Join(dpop.ErrInvalidProof, err) 95 } 96 b64URLjwkHash := base64.RawURLEncoding.EncodeToString(h.Sum(nil)) 97 98 return b64URLjwkHash, claims.Nonce, nil 99}