-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for public key per-token and add an example
Relative to: #2
- Loading branch information
Showing
4 changed files
with
122 additions
and
16 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"time" | ||
|
||
"github.com/kataras/jwt" | ||
) | ||
|
||
// Claims is an example of custom claims. | ||
type Claims struct { | ||
Email string `json:"email"` | ||
} | ||
|
||
func main() { | ||
privateKey, err := jwt.LoadPrivateKeyRSA("../../_testfiles/rsa_private_key.pem") | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
// Generate a token with custom claims and custom jwt header. | ||
claims := Claims{Email: "[email protected]"} | ||
header := Header{ | ||
Kid: "my_key_id_1", | ||
Alg: jwt.RS256.Name(), | ||
} | ||
token, err := jwt.SignWithHeader(jwt.RS256, privateKey, claims, header, jwt.MaxAge(10*time.Minute)) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
log.Printf("Generated token: %s", token) | ||
|
||
// Verify the token with a custom header validator and public key per-token. | ||
verifiedToken, err := jwt.VerifyWithHeaderValidator(jwt.RS256, nil, token, validateHeader) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
var getClaims Claims | ||
err = verifiedToken.Claims(&getClaims) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
log.Printf("Verified claims: %#+v", getClaims) | ||
} | ||
|
||
var keys = map[string][]byte{ | ||
"my_key_id_1": []byte(`-----BEGIN PUBLIC KEY----- | ||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw6OJ4K9LUz6MugrF7uB+ | ||
/oZw8/f3J4CSPYZFXMTsWNVQSLlen6/pr7ZvyPsgLvBGikybxRu7ff6ufmHTWTm7 | ||
mlpxEv/bgFFUmfH/faY7SA1PJcWMaEMT6s7E96orefyTMNdLi4OKhUGYJ56L8cE1 | ||
yRIya+B2UMCg2ItK11TRQlHLwvKRGsFFirc23oHX8gMuduEkIb5dSD6rEaopR3ZM | ||
O1tipfNrlCZs5kTaIubFRJ6K1xy2Rk2hVhqdaX6Ud2aWwrb7o21REkDbqY9YuOGV | ||
/FnDiqDtIoS7MHl5CAguaL9YiOv3RRvCrUttfuHqbljlD7m6/69rMB1cVfbdr5IB | ||
RQIDAQAB | ||
-----END PUBLIC KEY----- | ||
`), | ||
// ...more keys | ||
} | ||
|
||
// Header is an example of custom header. | ||
type Header struct { | ||
Kid string `json:"kid"` | ||
Alg string `json:"alg"` | ||
} | ||
|
||
func validateHeader(alg string, headerDecoded []byte) (jwt.PublicKey, error) { | ||
var h Header | ||
err := jwt.Unmarshal(headerDecoded, &h) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if h.Alg != alg { | ||
return nil, jwt.ErrTokenAlg | ||
} | ||
|
||
if h.Kid == "" { | ||
return nil, fmt.Errorf("kid is empty") | ||
} | ||
|
||
key, ok := keys[h.Kid] | ||
if !ok { | ||
return nil, fmt.Errorf("unknown kid") | ||
} | ||
|
||
publicKey, err := jwt.ParsePublicKeyRSA(key) | ||
if err != nil { | ||
return nil, jwt.ErrTokenAlg | ||
} | ||
|
||
return publicKey, nil | ||
} |
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