gbrlsnchs / jwt Goto Github PK
View Code? Open in Web Editor NEWGo JWT signing, verifying and validating
License: MIT License
Go JWT signing, verifying and validating
License: MIT License
To prevent an issue to take too long to be resolved, some info should be asked beforehand.
Right now, the Audience value is defined as a string in the JWT struct:
https://github.com/gbrlsnchs/jwt/blob/master/jwt.go#L17
And the Audience validator checks string == string:
https://github.com/gbrlsnchs/jwt/blob/master/validators.go#L29-L37
But the JWT spec for audience claims says that aud can be a string or a list of strings:
https://tools.ietf.org/html/rfc7519#section-4.1.3
This is how auth0/node-jsonwebtoken deals with aud too:
The audience can be checked against a string, a regular expression or a list of strings and/or regular expressions. Eg: "urn:foo", /urn:f[o]{2}/, [/urn:f[o]{2}/, "urn:bar"]
https://github.com/auth0/node-jsonwebtoken/tree/master
Would you be open to a PR that dealt with aud to cover the case where it's a list of strings and not just a string?
Or is there some reason why you won't want to make that change?
Hi,
I'm still new with authentication thing
How can i get the user information through the token?
is it okay if i input user detail such as name, email, etc in the Token
struct?
then is it okay if i unmarshal the token and return the information inside the Token?
go get -u github.com/gbrlsnchs/jwt/v3
package github.com/gbrlsnchs/jwt/v3: cannot find package "github.com/gbrlsnchs/jwt/v3" in any of:
C:\Go\src\github.com\gbrlsnchs\jwt\v3 (from $GOROOT)
C:\Users\mukon\Desktop\go\src\github.com\gbrlsnchs\jwt\v3 (from $GOPATH)
Is your feature request related to a problem? Please describe.
So currently the library does not provide a way for parsing JWK from URLs as is often necessary when working with some libraries, I had this requirement using auth0
and ory/hydra
but this is a common pattern so I am sure this would be a useful feature.
Describe the solution you'd like
So I was thinking of an elegant solution that would be concise and type-safe for the user, an example of what I mean is as follows:
var keys []*rsa.PublicKey
err := jwt.GetKeysFromURL(someURL, &keys)
if err != nil {
log.Fatalf("unable to get keys from URL %s, reason: %s", someURL, err)
}
fmt.Println("number of loaded keys:", len(keys))
And for files:
var keys []*rsa.PublicKey
err := jwt.GetKeysFromURL(filePath, &keys)
if err != nil {
log.Fatalf("unable to get keys from file %s, reason: %s", filePath, err)
}
fmt.Println("number of loaded keys:", len(keys))
The idea is that the user would be able to pass a list of any type of key he wants and we would parse the JSON from the URL or File and then type-assert the input list to see if it matches what we expect, if yes we fill it, if not we return an error.
I believe it would be possible to implement this without using any reflection, we would probably just need a switch input.(type) {...}
construct to handle the different inputs, and I would be glad to make a PR if you like the idea.
Describe alternatives you've considered
I've solved this problem when working with github.com/lestrrat-go/jwx, but I didn't like the way that library does it, it converts the keys into an internal representation and forces the user to iterate over all the keys and manually convert them to the desired type.
I have also considered implementing it myself using this example I found online specific for RSA keys:
https://stackoverflow.com/a/66739021/2905274
But this is a complex function and I don't want to replicate it on all my microservices if I can avoid it.
So what do you think?
hi all.
I've tried with repo's example using CustomPayload
and i got this token
ZXlKaGJHY2lPaUpJVXpJMU5pSXNJbXRwWkNJNkltMWhjM1JsY2tCaFpHMXBiaTVqYjIwaUxDSjBlWEFpT2lKS1YxUWlmUS5leUpwYzNNaU9pSmhaRzFwYmlJc0luTjFZaUk2SWtGMWRHaGxiblJwWTJGMGFXOXVTbGRVSWl3aVlYVmtJanBiSW1oMGRIQnpPaTh2YUdGemRYSmhMbWx2TDJwM2RDOWpiR0ZwYlhNaUxDSm9kSFJ3Y3pvdkwycDNkQzVwYnlKZExDSmxlSEFpT2pFMU9UTTBPVFkxT0RZc0ltNWlaaUk2TVRVMk1qTTVORE00Tml3aWFXRjBJam94TlRZeU16a3lOVGcyTENKcWRHa2lPaUptYjI5aVlYSWlmUS5NS0hhYTRiSGZsNVBDUFp0d3R4cEc0TjByWmNpbktjSjlDckhSRU9YN3dr
There are nothing dot separated three part as JWT. I'm tried decode at http://calebb.net/ got error message JWT is required to have three segments
What wrong with me?
This is my code
type Login struct {
Email string `json:"email" binding:"required"`
Password string `json:"password" binding:"required"`
}
type CustomPayload struct {
jwt.Payload
Authenticated bool `json:"authenticated"`
Role string `json:"role"`
}
func authenticate(login *Login) (error, []byte) {
now := time.Now()
hs256 := jwt.NewHMAC(jwt.SHA256, []byte(login.Password))
header := jwt.Header{KeyID: "keyid"}
payload := CustomPayload{
Payload: jwt.Payload{
Issuer: "admin",
Subject: "AuthenticationJWT",
Audience: jwt.Audience{"https://hasura.io/jwt/claims", "https://jwt.io"},
ExpirationTime: now.Add(24 * 30 * 12 * time.Hour).Unix(),
NotBefore: now.Add(30 * time.Minute).Unix(),
IssuedAt: now.Unix(),
JWTID: "foobar",
},
Authenticated: true,
Role: "user",
}
token, err := jwt.Sign(header, payload, hs256)
if err != nil {
log.Printf("jwt.Sign() err: %v\n", err)
return err, nil
}
log.Print("token: %s\n", token)
return nil, token
}
It looks like ed25519 is excluded from 1.13 builds (See line 1 here and here - // +build !go1.13
).
Now that 1.13 is released and support for ed25519 is officially in crypto/ed25519
, can we make this available for 1.13?
I would be willing to do a PR. I'm assuming you would prefer ed25519_go1_13.go
files with // +build go1.13
and the import switched to crypto/ed25519
since build constraints are at the file level?
I think the default will check the expiration time usually...but not...I thought it was a bug.
Will it be in v3.1 ?
Will the sub
type of the payload support other data types?
I noticed that in some other projects, sub
may be a map or an int type. Does sub
have plans to support other types in the future?
I wonder if I can use map[string]interface{} in place of the CustomPayload? I think that way it will be a lot easier to use the api.
Maybe I'm missing something, but why do you recommend embedding a pointer in your claims and why embed a pointer to header?
I have nothing against pointers in general, but I don't think they're necessary here or here (please correct me) and if they're not necessary, I tend to avoid using them...
I'm mostly just curious.
An early 3.0 beta allowed me to parse a token to get the header. I would use this to get the kid to look up the public key for verifying.
Now it seems I have to specify what kind of token it is (RS256, ES512, etc) before getting the header. Is this correct?
One of my favorite tools is the jwt.io site. I can paste in a token to get the header and payload. Shouldn't I be able to get the same data from the jwt package without going through a verify function?
Consider removing golang.org/x/xerrors dependency. I know it doesn't matter using type aliases but still I prefer deprecating it sooner than later :) Thanks. JWT is the only dependency in my mod list that relies on xerrors.
I'm unsure if this is production ready...it seems to be the most complete -- there are only two libraries that bother to validate the all the fields in a claim...
RT...
您好,这个包里面实现了token自动刷新续期的功能了吗,我看了下源码好像没有这个功能
CircleCI seems to be more modern overall. Move Linux/macOS CI to CircleCI and Windows CI back to AppVeyor.
Just curious...Why not ?
Is there any way to extract claims from token like in this package (any example appreciated)?
For some reason I can not get hold of 'alg' from the header. Any suggestions, please?
Type and Payload data are available and properly Unmarshal-ed.
payload, sig, err := jwt.Parse(tokenString)
if err != nil {
return nil, errors.New("token invalid: " + err.Error())
}
if err = jwt.Unmarshal(payload, &token); err != nil {
return nil, errors.New("token malformed: " + err.Error())
}
log.Log("Parsing token....")
log.Log("alg is" + token.Algorithm())
log.Log("typ is" + token.Type())
I'm new to go.
and I'm having problem with NewES256(priv *priv_key,pub *public_key)
how to pass .pem file contents to the function.
Passing string from file give
./server.go:17:22: cannot use private_key (type string) as type *ecdsa.PrivateKey in argument to jwt.NewES256
./server.go:17:22: cannot use public_key (type string) as type *ecdsa.PublicKey in argument to jwt.NewES256
how should i convert it to *ecdsa.PrivateKey and *ecdsa.PublicKey respectively?
Describe the bug
Verification isn't working for the examples with HMAC. If i go onto JWT.IO and manually paste the JWT and enter the secret, everything works as expected.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
Verification isn't happening as expected
Please complete the following information:
Additional context
Support the following signing methods:
when writing,
var jot Token
i get Error,
undefined: Token
Do i have to define it? if so how?
I'm currently trying to use this package again after not using it for a while and my previously working code no longer functions as intended, furthermore I don't seem to be able to use "github.com/gbrlsnchs/jwt/v3"
anymore either. Adopting this module at this point in time for me is rather troublesome, I have also sent a few messages in gitter but that seems disused.
The validation functions jwt. IssuedAtValidator
, jwt.ExpirationTimeValidator
, and jwt.NotBeforeValidator
evaluate the "iat," "exp," and "nbf" claims against a given time, respectively. All three of them use the corresponding claim value as the number of seconds since the Unix epoch. However, if any of the claims aren't set, the claim value will be zero, which may or may not mean that the intended time was the start of the Unix epoch.
Ideally we'd be able to distinguish between the field being set or not, perhaps by storing the int64
value as a pointer. If the claim value is nil, it's not set; if it's present and zero, it is set to the start of the Unix epoch.
Now, you could argue that 1 January 1970 is far enough in the past that we don't need to worry about it being close to any times we'll find in tokens today, but jwt.ExpirationTimeValidator
checks whether the given time is after the claim value. For tokens that don't expire, they'll all appear as though they've already expired today.
Potential solutions:
jwt.Claims
type to store these fields as pointers.I favor the second solution, if you can accept the change in the package interface.
I am looking at the master
branch.
The Verify() func doesn't check the header alg
against the verifier it was provided. While I don't see vulnerability here, like the one that verifies ES256 with HS256 verifier[1], as far as I can tell, it doesn't comply with the specification[2]. In the general case, RawToken.Verify() should check if the Verifier is suitable for the specific token alg
and otherwise return an error.
Refs:
[1] https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/
[2] https://tools.ietf.org/html/rfc7519 Section 7.2 Article 5
Decode a base64 encode token get the payload info, look like :
{"typ":"JWT","alg":"HS256","jti":"e6ca395f2a6479f9a84739e339544aec"}
Now I want to get the alg: HS256
item of a encode token, How should I do or I need to handle the string by myself?
Adding gbrlsnchs/jwt
to a go.mod
file
and running go mod download
is giving this error
go: github.com/gbrlsnchs/[email protected]: go.mod has post-v0 module path "github.com/gbrlsnchs/jwt/v2" at revision 808efa0714ba
go: error loading module requirements
Go Version: go1.11.4 darwin/amd64
Hi, I'm trying to decode the token but it throws index out of range
panic: runtime error: index out of range
goroutine 9 [running]:
github.com/gbrlsnchs/jwt/v3.(*Audience).UnmarshalJSON(0xc0001216a0, 0xc00006616e, 0xf, 0x43, 0x7fa7fb14c158, 0xc0001216a0)
/go/pkg/mod/github.com/gbrlsnchs/jwt/[email protected]/audience.go:39 +0x1df
encoding/json.(*decodeState).array(0xc00016f680, 0x930ec0, 0xc0001216a0, 0x197, 0xc00016f6a8, 0x5b)
/usr/local/go/src/encoding/json/decode.go:505 +0xc6d
encoding/json.(*decodeState).value(0xc00016f680, 0x930ec0, 0xc0001216a0, 0x197, 0x930ec0, 0xc0001216a0)
/usr/local/go/src/encoding/json/decode.go:371 +0xff
encoding/json.(*decodeState).object(0xc00016f680, 0x929120, 0xc000121680, 0x16, 0xc00016f6a8, 0xc00018c87b)
/usr/local/go/src/encoding/json/decode.go:763 +0x1899
encoding/json.(*decodeState).value(0xc00016f680, 0x929120, 0xc000121680, 0x16, 0xc0002176c0, 0x52fd27)
/usr/local/go/src/encoding/json/decode.go:381 +0x6e
encoding/json.(*decodeState).unmarshal(0xc00016f680, 0x929120, 0xc000121680, 0xc00016f6a8, 0x0)
/usr/local/go/src/encoding/json/decode.go:179 +0x1fe
encoding/json.Unmarshal(0xc000066150, 0x61, 0x61, 0x929120, 0xc000121680, 0x82, 0xb9)
/usr/local/go/src/encoding/json/decode.go:106 +0x123
github.com/gbrlsnchs/jwt/v3.RawToken.Decode(0xc00037c5a0, 0xe5, 0xf0, 0x36, 0xb9, 0xc000065c80, 0x929120, 0xc000121680, 0x0, 0x0)
/go/pkg/mod/github.com/gbrlsnchs/jwt/[email protected]/raw_token.go:65 +0x327
I'm using the default jwt.Payload and the v3 branch
Token example:
eyJhbGciOiJIUzI1NiIsImtpZCI6ImF1dGgiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJhdXRoIiwic3ViIjoiMSIsImF1ZCI6WyJhZG0iXSwiZXhwIjoxNTgyOTk5OTg5LCJuYmYiOjE1NTE4OTc3ODksImlhdCI6MTU1MTg5NTk4OX0.SGsv7DBtpjkJZeRaikcWO48UXG7aPRpmIEPMesQQVqQ
:$ go version$ go get -u github.com/gbrlsnchs/jwt/v3
go version go1.14.3 linux/amd64
:
package github.com/gbrlsnchs/jwt/v3: cannot find package "github.com/gbrlsnchs/jwt/v3" in any of:
/usr/lib/newgo/go/src/github.com/gbrlsnchs/jwt/v3 (from $GOROOT)
:$ GO111MODULE=on$ go get -u github.com/gbrlsnchs/jwt/v3
:
package github.com/gbrlsnchs/jwt/v3: cannot find package "github.com/gbrlsnchs/jwt/v3" in any of:
/usr/lib/newgo/go/src/github.com/gbrlsnchs/jwt/v3 (from $GOROOT)
When I did go get github.com/gbrlsnchs/jwt
It shown pub.size undefined(type *rsa.PublicKey has no field or method Size)
Pls show me how to solve it.
Support Ed25519 by using https://godoc.org/golang.org/x/crypto/ed25519.
Per RFC 7519:
The "jti" (JWT ID) claim provides a unique identifier for the JWT... The "jti" claim can be used
to prevent the JWT from being replayed.
The current implementation of jti validation simply looks for an exact match against a specified value. So it's not so much looking for uniqueness across different JWTs, but rather that the JWT has a pre-defined ID.
I have a private key and token signed by alg rs256, could you describe how to work with your library? You have no examples.
vgo get -u github.com/gbrlsnchs/jwt/v2
and go get -u github.com/gbrlsnchs/jwt/v2
Hi @gbrlsnchs
I've been testing ed25519 signing of jwts, which I have been generating with python's jwt module. The jwt I'm using is here.
My comments are in relation to RFC8037/A.5.
Excuse me if I'm making a stupid error.
Describe the bug
A jwt constructed with a ed25519 keypair errors in ValidateHeader
with "EdDSA": invalid "alg" field
To Reproduce
hd, err := jwt.Verify(token, k, &pl, validatePayload, jwt.ValidateHeader)
if err != nil {
fmt.Println(err)
}
See https://gist.github.com/b8a093bdd3f2a4ccb7e12831b37a5154 for a full example
It appears that ValidateHeader
in verify.go is depending on _ Algorithm = new(Ed25519)
in ed25519.go. I believe that name is incorrect for an ed25519 signed jwt:
// ValidateHeader checks whether the algorithm contained
// in the JOSE header is the same used by the algorithm.
func ValidateHeader(rt *RawToken) error {
if rt.alg.Name() != rt.hd.Algorithm {
return internal.Errorf("jwt: %q: %w", rt.hd.Algorithm, ErrAlgValidation)
}
return nil
}
Expected behavior
That the "alg": "EdDSA"
be accepted for ed25519 signed jwts.
Perhaps It would also be good for the user to explicitly state the accepted algorithms, as suggested by jwt.io's advice to check signatures. The explicit argument of algorithms=["RS256"]
for example, given in pyjwt, might be worth considering.
Please complete the following information:
one.
hd, err := jwt.Verify(token, hs, &pl)
two.
hd, err = jwt.Verify(token, hs, &pl, ValidatePayload)
I created expValidator
and nbfValidator
, The hd are the same.
So, What is the verification? I mean the process. It won't panic even time's expired or nbf-time is expired, Work of the lib is just parse claims?
That is my problem.
Getting jwt: malformed token
with the following:
// My own private code...
var Auth = AuthUtils{
HS: jwt.NewHS256([]byte("wizard123")),
}
Signing seems to work ok:
now := time.Now()
payload := utils.LoginPayload{
Payload: jwt.Payload{
//Issuer: "edorial.com",
//Subject: "login",
//Audience: jwt.Audience{"http://edorial.com"},
ExpirationTime: jwt.NumericDate(now.Add(24 * 30 * 12 * time.Hour)),
//NotBefore: jwt.NumericDate(now.Add(30 * time.Minute)),
IssuedAt: jwt.NumericDate(now),
JWTID: "id",
},
Id: 0,
}
token, err := jwt.Sign(payload, utils.Auth.HS)
But when I verify the token it throws
// Private code ----------------->
authHeaderValue := c.Request.Header.Get("Authorization")
token := strings.Split(strings.ToLower(authHeaderValue), "bearer")
if len(token) < 2 {
c.AbortWithStatus(http.StatusForbidden)
return
}
tokeBytes := []byte(token[1])
// End private code <------------------------
var payload utils.LoginPayload
hd, err := jwt.Verify(tokeBytes, utils.Auth.HS, &payload); if err != nil {
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{
"error": err.Error(), // "error": "jwt: malformed token"
})
return
}
I think restricting from older versions is not a good move. Major version bumps can be managed with gopkg.in for Go versions before 1.10 and for 1.10 there's vgo
.
This also implies in (*RSA).Size
having to be hard coded somehow for older versions.
Edit: take this opportunity to enhance README.
Edit 2: I'll follow this guidance and try to support go1.9.7
, go1.10.3
and every subsequent version.
In issue #15 I was asked about storing user information within the token. Of course, with only JWS, it is not safe, since user information would be stored client side. However, we could fix it by using JWE, which this library doesn't support right now.
I think this library could benefit from supporting JWE too. v2
was designed to fix performance issues with v1
, but it is too verbose and doesn't allow JWE to be implemented so easily (actually, I think implementing JWE in v2
would force a major version bump anyway).
References:
https://tools.ietf.org/html/rfc7516
In the github.com/dgrijalva/jwt-go package, there are two token consuming functions—Parse
and ParseWithClaims
—that accept a callback of type Keyfunc
, allowing the caller to first see a token's "alg" and "kid" header values in order to select which key to use for verifying the token. Is it possible to do something similar with this package?
I see that as of version 3, one can call jwt.Verify
to get a jwt.RawToken
back, but that requires that the caller know a priori which verifier to use. This interface works well enough for consumers that accept only a single signing method (algorithm and hash), but it isn't sufficient for consumers that want to react to the declarations in the token's header to choose from several available verification options.
Of course, it's possible to keep calling jwt.Verify
with different Verifier
s, but that wastes work finding the three components of the token each time. Am I missing another approach?
Hi,
Is there a way to decode claims without passing a secret?
It's required something before the actual token verification
Right now it's mandatory to pass hs
Thanks
when writing,
var jot Token
i get Error,
undefined: Token
Do i have to define it? if so how?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.