forked from hailey.at/cocoon
An atproto PDS written in Go

improve dpop nonce error (#26)

+6 -2
oauth/dpop/manager.go
··· 36 Hostname string 37 } 38 39 func NewManager(args ManagerArgs) *Manager { 40 if args.Logger == nil { 41 args.Logger = slog.Default() ··· 194 nonce, _ := claims["nonce"].(string) 195 if nonce == "" { 196 // WARN: this _must_ be `use_dpop_nonce` for clients know they should make another request 197 - return nil, errors.New("use_dpop_nonce") 198 } 199 200 if nonce != "" && !dm.nonce.Check(nonce) { 201 // WARN: this _must_ be `use_dpop_nonce` so that clients will fetch a new nonce 202 - return nil, errors.New("use_dpop_nonce") 203 } 204 205 ath, _ := claims["ath"].(string)
··· 36 Hostname string 37 } 38 39 + var ( 40 + ErrUseDpopNonce = errors.New("use_dpop_nonce") 41 + ) 42 + 43 func NewManager(args ManagerArgs) *Manager { 44 if args.Logger == nil { 45 args.Logger = slog.Default() ··· 198 nonce, _ := claims["nonce"].(string) 199 if nonce == "" { 200 // WARN: this _must_ be `use_dpop_nonce` for clients know they should make another request 201 + return nil, ErrUseDpopNonce 202 } 203 204 if nonce != "" && !dm.nonce.Check(nonce) { 205 // WARN: this _must_ be `use_dpop_nonce` so that clients will fetch a new nonce 206 + return nil, ErrUseDpopNonce 207 } 208 209 ath, _ := claims["ath"].(string)
+8 -1
server/handle_oauth_par.go
··· 1 package server 2 3 import ( 4 "time" 5 6 "github.com/Azure/go-autorest/autorest/to" 7 "github.com/haileyok/cocoon/internal/helpers" 8 "github.com/haileyok/cocoon/oauth" 9 "github.com/haileyok/cocoon/oauth/constants" 10 "github.com/haileyok/cocoon/oauth/provider" 11 "github.com/labstack/echo/v4" 12 ) ··· 31 // TODO: this seems wrong. should be a way to get the entire request url i believe, but this will work for now 32 dpopProof, err := s.oauthProvider.DpopManager.CheckProof(e.Request().Method, "https://"+s.config.Hostname+e.Request().URL.String(), e.Request().Header, nil) 33 if err != nil { 34 s.logger.Error("error getting dpop proof", "error", err) 35 - return helpers.InputError(e, to.StringPtr(err.Error())) 36 } 37 38 client, clientAuth, err := s.oauthProvider.AuthenticateClient(e.Request().Context(), parRequest.AuthenticateClientRequestBase, dpopProof, &provider.AuthenticateClientOptions{
··· 1 package server 2 3 import ( 4 + "errors" 5 "time" 6 7 "github.com/Azure/go-autorest/autorest/to" 8 "github.com/haileyok/cocoon/internal/helpers" 9 "github.com/haileyok/cocoon/oauth" 10 "github.com/haileyok/cocoon/oauth/constants" 11 + "github.com/haileyok/cocoon/oauth/dpop" 12 "github.com/haileyok/cocoon/oauth/provider" 13 "github.com/labstack/echo/v4" 14 ) ··· 33 // TODO: this seems wrong. should be a way to get the entire request url i believe, but this will work for now 34 dpopProof, err := s.oauthProvider.DpopManager.CheckProof(e.Request().Method, "https://"+s.config.Hostname+e.Request().URL.String(), e.Request().Header, nil) 35 if err != nil { 36 + if errors.Is(err, dpop.ErrUseDpopNonce) { 37 + return e.JSON(400, map[string]string{ 38 + "error": "use_dpop_nonce", 39 + }) 40 + } 41 s.logger.Error("error getting dpop proof", "error", err) 42 + return helpers.InputError(e, nil) 43 } 44 45 client, clientAuth, err := s.oauthProvider.AuthenticateClient(e.Request().Context(), parRequest.AuthenticateClientRequestBase, dpopProof, &provider.AuthenticateClientOptions{
+8 -1
server/handle_oauth_token.go
··· 4 "bytes" 5 "crypto/sha256" 6 "encoding/base64" 7 "fmt" 8 "slices" 9 "time" ··· 13 "github.com/haileyok/cocoon/internal/helpers" 14 "github.com/haileyok/cocoon/oauth" 15 "github.com/haileyok/cocoon/oauth/constants" 16 "github.com/haileyok/cocoon/oauth/provider" 17 "github.com/labstack/echo/v4" 18 ) ··· 44 45 proof, err := s.oauthProvider.DpopManager.CheckProof(e.Request().Method, e.Request().URL.String(), e.Request().Header, nil) 46 if err != nil { 47 s.logger.Error("error getting dpop proof", "error", err) 48 - return helpers.InputError(e, to.StringPtr(err.Error())) 49 } 50 51 client, clientAuth, err := s.oauthProvider.AuthenticateClient(e.Request().Context(), req.AuthenticateClientRequestBase, proof, &provider.AuthenticateClientOptions{
··· 4 "bytes" 5 "crypto/sha256" 6 "encoding/base64" 7 + "errors" 8 "fmt" 9 "slices" 10 "time" ··· 14 "github.com/haileyok/cocoon/internal/helpers" 15 "github.com/haileyok/cocoon/oauth" 16 "github.com/haileyok/cocoon/oauth/constants" 17 + "github.com/haileyok/cocoon/oauth/dpop" 18 "github.com/haileyok/cocoon/oauth/provider" 19 "github.com/labstack/echo/v4" 20 ) ··· 46 47 proof, err := s.oauthProvider.DpopManager.CheckProof(e.Request().Method, e.Request().URL.String(), e.Request().Header, nil) 48 if err != nil { 49 + if errors.Is(err, dpop.ErrUseDpopNonce) { 50 + return e.JSON(400, map[string]string{ 51 + "error": "use_dpop_nonce", 52 + }) 53 + } 54 s.logger.Error("error getting dpop proof", "error", err) 55 + return helpers.InputError(e, nil) 56 } 57 58 client, clientAuth, err := s.oauthProvider.AuthenticateClient(e.Request().Context(), req.AuthenticateClientRequestBase, proof, &provider.AuthenticateClientOptions{
+8 -1
server/middleware.go
··· 3 import ( 4 "crypto/sha256" 5 "encoding/base64" 6 "fmt" 7 "strings" 8 "time" ··· 11 "github.com/golang-jwt/jwt/v4" 12 "github.com/haileyok/cocoon/internal/helpers" 13 "github.com/haileyok/cocoon/models" 14 "github.com/haileyok/cocoon/oauth/provider" 15 "github.com/labstack/echo/v4" 16 "gitlab.com/yawning/secp256k1-voi" ··· 229 230 proof, err := s.oauthProvider.DpopManager.CheckProof(e.Request().Method, "https://"+s.config.Hostname+e.Request().URL.String(), e.Request().Header, to.StringPtr(accessToken)) 231 if err != nil { 232 s.logger.Error("invalid dpop proof", "error", err) 233 - return helpers.InputError(e, to.StringPtr(err.Error())) 234 } 235 236 var oauthToken provider.OauthToken
··· 3 import ( 4 "crypto/sha256" 5 "encoding/base64" 6 + "errors" 7 "fmt" 8 "strings" 9 "time" ··· 12 "github.com/golang-jwt/jwt/v4" 13 "github.com/haileyok/cocoon/internal/helpers" 14 "github.com/haileyok/cocoon/models" 15 + "github.com/haileyok/cocoon/oauth/dpop" 16 "github.com/haileyok/cocoon/oauth/provider" 17 "github.com/labstack/echo/v4" 18 "gitlab.com/yawning/secp256k1-voi" ··· 231 232 proof, err := s.oauthProvider.DpopManager.CheckProof(e.Request().Method, "https://"+s.config.Hostname+e.Request().URL.String(), e.Request().Header, to.StringPtr(accessToken)) 233 if err != nil { 234 + if errors.Is(err, dpop.ErrUseDpopNonce) { 235 + return e.JSON(400, map[string]string{ 236 + "error": "use_dpop_nonce", 237 + }) 238 + } 239 s.logger.Error("invalid dpop proof", "error", err) 240 + return helpers.InputError(e, nil) 241 } 242 243 var oauthToken provider.OauthToken