-
Notifications
You must be signed in to change notification settings - Fork 206
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add square/go-jose.v2 token validator (#84)
- Loading branch information
1 parent
23c6193
commit 665e7da
Showing
14 changed files
with
716 additions
and
98 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,118 @@ | ||
# GO JWT Middleware | ||
|
||
[![GoDoc Widget]][GoDoc] | ||
|
||
**WARNING** | ||
This `v2` branch is not production ready - use at your own risk. | ||
|
||
TODO: update this README in the `v2` branch. We're waiting so as not to hold everything up in the testing branch. Also some of the default validation logic needs to be added here. | ||
Golang middleware to check and validate [JWTs](jwt.io) in the request and add the valid token contents to the request context. | ||
|
||
## Installation | ||
``` | ||
go get github.com/auth0/go-jwt-middleware | ||
``` | ||
|
||
## Usage | ||
```golang | ||
package main | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
|
||
jwtmiddleware "github.com/auth0/go-jwt-middleware" | ||
"github.com/auth0/go-jwt-middleware/validate/josev2" | ||
"gopkg.in/square/go-jose.v2" | ||
"gopkg.in/square/go-jose.v2/jwt" | ||
) | ||
|
||
## What is Auth0? | ||
var handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
user := r.Context().Value(jwtmiddleware.ContextKey{}) | ||
j, err := json.MarshalIndent(user, "", "\t") | ||
if err != nil { | ||
w.WriteHeader(http.StatusInternalServerError) | ||
fmt.Println(err) | ||
} | ||
|
||
Auth0 helps you to: | ||
fmt.Fprintf(w, "This is an authenticated request") | ||
fmt.Fprintf(w, "Claim content:\n") | ||
fmt.Fprint(w, string(j)) | ||
}) | ||
|
||
* Add authentication with [multiple authentication sources](https://docs.auth0.com/identityproviders), either social like **Google, Facebook, Microsoft Account, LinkedIn, GitHub, Twitter, Box, Salesforce, amont others**, or enterprise identity systems like **Windows Azure AD, Google Apps, Active Directory, ADFS or any SAML Identity Provider**. | ||
* Add authentication through more traditional **[username/password databases](https://docs.auth0.com/mysql-connection-tutorial)**. | ||
* Add support for **[linking different user accounts](https://docs.auth0.com/link-accounts)** with the same user. | ||
* Support for generating signed [Json Web Tokens](https://docs.auth0.com/jwt) to call your APIs and **flow the user identity** securely. | ||
* Analytics of how, when and where users are logging in. | ||
* Pull data from other sources and add it to the user profile, through [JavaScript rules](https://docs.auth0.com/rules). | ||
func main() { | ||
keyFunc := func(ctx context.Context) (interface{}, error) { | ||
// our token must be signed using this data | ||
return []byte("secret"), nil | ||
} | ||
|
||
## Create a free Auth0 Account | ||
expectedClaimsFunc := func() jwt.Expected { | ||
// By setting up expected claims we are saying a token must | ||
// have the data we specify. | ||
return jwt.Expected{ | ||
Issuer: "josev2-example", | ||
} | ||
} | ||
|
||
1. Go to [Auth0](https://auth0.com) and click Sign Up. | ||
2. Use Google, GitHub or Microsoft Account to login. | ||
// setup the piece which will validate tokens | ||
validator, err := josev2.New( | ||
keyFunc, | ||
jose.HS256, | ||
josev2.WithExpectedClaims(expectedClaimsFunc), | ||
) | ||
if err != nil { | ||
// we'll panic in order to fail fast | ||
panic(err) | ||
} | ||
|
||
// setup the middleware | ||
m := jwtmiddleware.New(validator.ValidateToken) | ||
|
||
http.ListenAndServe("0.0.0.0:3000", m.CheckJWT(handler)) | ||
} | ||
``` | ||
|
||
Running that code you can then curl it from another terminal: | ||
``` | ||
$ curl -H Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJpc3MiOiJqb3NldjItZXhhbXBsZSJ9.e0lGglk9-m-n-t07eA5f7qgXGM-nD4ekwJkYVKprIUM" localhost:3000 | ||
``` | ||
should give you the response | ||
``` | ||
This is an authenticated requestClaim content: | ||
{ | ||
"CustomClaims": null, | ||
"Claims": { | ||
"iss": "josev2-example", | ||
"sub": "1234567890", | ||
"iat": 1516239022 | ||
} | ||
} | ||
``` | ||
The JWT included in the Authorization header above is signed with `secret`. | ||
|
||
To test it not working: | ||
``` | ||
$ curl -v -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.yiDw9IDNCa1WXCoDfPR_g356vSsHBEerqh9IvnD49QE" localhost:3000 | ||
``` | ||
should give you a response like | ||
``` | ||
... | ||
< HTTP/1.1 401 Unauthorized | ||
... | ||
``` | ||
|
||
## Issue Reporting | ||
|
||
If you have found a bug or if you have a feature request, please report them at this repository issues section. Please do not report security vulnerabilities on the public GitHub issue tracker. The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues. | ||
|
||
## Author | ||
|
||
[Auth0](auth0.com) | ||
[Auth0](https://auth0.com/) | ||
|
||
## License | ||
|
||
This project is licensed under the MIT license. See the [LICENSE](LICENSE) file for more info. | ||
|
||
[GoDoc]: https://pkg.go.dev/github.com/auth0/go-jwt-middleware | ||
[GoDoc Widget]: https://pkg.go.dev/badge/github.com/auth0/go-jwt-middleware.svg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,44 +1,57 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
|
||
jwtmiddleware "github.com/auth0/go-jwt-middleware" | ||
"github.com/form3tech-oss/jwt-go" | ||
"github.com/auth0/go-jwt-middleware/validate/josev2" | ||
"gopkg.in/square/go-jose.v2" | ||
"gopkg.in/square/go-jose.v2/jwt" | ||
) | ||
|
||
// TODO: replace this with default validate token func once it is merged in | ||
func REPLACE_ValidateToken(token string) (interface{}, error) { | ||
// Now parse the token | ||
parsedToken, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) { | ||
return []byte("My Secret"), nil | ||
}) | ||
|
||
// Check if there was an error in parsing... | ||
var handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
user := r.Context().Value(jwtmiddleware.ContextKey{}) | ||
j, err := json.MarshalIndent(user, "", "\t") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Check if the parsed token is valid... | ||
if !parsedToken.Valid { | ||
return nil, jwtmiddleware.ErrJWTInvalid | ||
w.WriteHeader(http.StatusInternalServerError) | ||
fmt.Println(err) | ||
} | ||
|
||
return parsedToken, nil | ||
} | ||
|
||
var myHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
user := r.Context().Value("user") | ||
fmt.Fprintf(w, "This is an authenticated request") | ||
fmt.Fprintf(w, "Claim content:\n") | ||
for k, v := range user.(*jwt.Token).Claims.(jwt.MapClaims) { | ||
fmt.Fprintf(w, "%s :\t%#v\n", k, v) | ||
} | ||
fmt.Fprint(w, string(j)) | ||
}) | ||
|
||
func main() { | ||
jwtMiddleware := jwtmiddleware.New(jwtmiddleware.WithValidateToken(REPLACE_ValidateToken)) | ||
keyFunc := func(ctx context.Context) (interface{}, error) { | ||
// our token must be signed using this data | ||
return []byte("secret"), nil | ||
} | ||
|
||
expectedClaimsFunc := func() jwt.Expected { | ||
// By setting up expected claims we are saying a token must | ||
// have the data we specify. | ||
return jwt.Expected{ | ||
Issuer: "josev2-example", | ||
} | ||
} | ||
|
||
// setup the piece which will validate tokens | ||
validator, err := josev2.New( | ||
keyFunc, | ||
jose.HS256, | ||
josev2.WithExpectedClaims(expectedClaimsFunc), | ||
) | ||
if err != nil { | ||
// we'll panic in order to fail fast | ||
panic(err) | ||
} | ||
|
||
// setup the middleware | ||
m := jwtmiddleware.New(validator.ValidateToken) | ||
|
||
http.ListenAndServe("0.0.0.0:3000", jwtMiddleware.CheckJWT(myHandler)) | ||
http.ListenAndServe("0.0.0.0:3000", m.CheckJWT(handler)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,24 @@ | ||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk= | ||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= | ||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= | ||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= | ||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | ||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= | ||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= | ||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | ||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= | ||
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.