karalabe / go-bluesky

Bluesky API client from Go
BSD 3-Clause "New" or "Revised" License
75 stars 11 forks source link

token is unverifiable: signing method (alg) is unavailable #5

Open eeshankeni opened 11 months ago

eeshankeni commented 11 months ago

Hi, I'm getting this error when trying to log in. Can confirm my handle and appkey are correct. If they are not, I do indeed get the second error. Right now it directly takes me to the third case and prints the error "token is unverifiable: signing method (alg) is unavailable"

blueSkyClient, err := bluesky.Dial(ctx, bluesky.ServerBskySocial)
if err != nil {
    panic(err)
}

defer blueSkyClient.Close()

err = blueSkyClient.Login(ctx, blueskyHandle, blueskyAppkey)

switch {
case errors.Is(err, bluesky.ErrMasterCredentials):
    panic("You're not allowed to use your full-access credentials, please create an appkey")
case errors.Is(err, bluesky.ErrLoginUnauthorized):
    panic("Username of application password seems incorrect, please double check")
case err != nil:
    fmt.Println(err)
    panic("Something else went wrong, please look at the returned error")
}
eeshankeni commented 11 months ago

Not exactly a "fix" but removing the error checking during decoding within the Login method fixed the issue for now.

// Verify and reject master credentials, sorry, no bad security practices
token, _, _ := jwt.NewParser().ParseUnverified(sess.AccessJwt, jwt.MapClaims{})

if token.Claims.(jwt.MapClaims)["scope"] != "com.atproto.appPass" {
    return fmt.Errorf("%w: %w", ErrLoginUnauthorized, ErrMasterCredentials)
}
// Retrieve the expirations for the current and refresh JWT tokens
current, err := token.Claims.GetExpirationTime()
if err != nil {
    return err
}

token, _, _ = jwt.NewParser().ParseUnverified(sess.AccessJwt, jwt.MapClaims{})

refresh, err := token.Claims.GetExpirationTime()
if err != nil {
    return err
}
// Construct the authenticated client and the JWT expiration metadata
c.client.Auth = &xrpc.AuthInfo{
    AccessJwt:  sess.AccessJwt,
    RefreshJwt: sess.RefreshJwt,
    Handle:     sess.Handle,
    Did:        sess.Did,
}
c.jwtCurrentExpire = current.Time
c.jwtRefreshExpire = refresh.Time
slimsag commented 10 months ago

I know +1 comments are not useful, but figured since this is a smaller project I'd mention I also ran into it.

racerxdl commented 2 months ago

So a better fix is:

  1. Install github.com/ureeves/jwt-go-secp256k1
  2. Create a wrapper (since it has incompatible signatures):

type es256k struct{}

func (e *es256k) Verify(signingString string, sig []byte, key interface{}) error { return secp256k1.SigningMethodES256K.Verify(signingString, string(sig), key) }

func (e *es256k) Sign(signingString string, key interface{}) ([]byte, error) { sig, err := secp256k1.SigningMethodES256K.Sign(signingString, key) if err != nil { return nil, err } return []byte(sig), nil }

func (e *es256k) Alg() string { return "ES256K" }

func init() { // Register ES256K signing method jwt.RegisterSigningMethod("ES256K", func() jwt.SigningMethod { return &es256k{} }) }


3. Profit!
dewey commented 1 day ago

I've tried to run this commit from Erisa and unfortunately I'm running into the following error. Was anyone else able to get it to work yet?

github.com/ethereum/go-ethereum/crypto/secp256k1
# github.com/ethereum/go-ethereum/crypto/secp256k1
vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/curve.go:42:10: fatal error: 'libsecp256k1/include/secp256k1.h' file not found
   42 | #include "libsecp256k1/include/secp256k1.h"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.