commit
71652a3d3a
@ -0,0 +1,2 @@
|
||||
go.mod
|
||||
*.txt
|
@ -0,0 +1,13 @@
|
||||
package nwjwt
|
||||
|
||||
type Header struct {
|
||||
Algorithm string `json:"alg"`
|
||||
Type string `json:"typ"`
|
||||
}
|
||||
|
||||
func DefaultHeader() Header {
|
||||
return Header{
|
||||
Algorithm: "HS256",
|
||||
Type: "JWT",
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package nwjwt
|
||||
|
||||
import "crypto/rand"
|
||||
|
||||
const (
|
||||
Issuer = "iss"
|
||||
Subject = "sub"
|
||||
Audience = "aud"
|
||||
Expiry = "exp"
|
||||
NotBefore = "nbf"
|
||||
IssuedAt = "iat"
|
||||
ID = "jti"
|
||||
)
|
||||
|
||||
//https://auth0.com/docs/security/tokens/json-web-tokens/json-web-token-claims
|
||||
//https://en.wikipedia.org/wiki/JSON_Web_Token
|
||||
//https://connect2id.com/products/nimbus-jose-jwt/examples/jwk-generation
|
||||
func GenerateSecret() []byte {
|
||||
key := make([]byte, 256)
|
||||
_, err := rand.Read(key)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return key
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package nwjwt
|
||||
|
||||
import (
|
||||
// "encoding/base64"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
o, _ := os.Create("test.txt")
|
||||
|
||||
// secret := GenerateSecret()
|
||||
// o.WriteString(base64.RawURLEncoding.EncodeToString(secret))
|
||||
// o.WriteString("\n")
|
||||
|
||||
token := NewToken()
|
||||
token.Claims[Expiry] = 1640212096
|
||||
|
||||
token.Sign([]byte("test"))
|
||||
|
||||
o.WriteString(token.String())
|
||||
o.Close()
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
package nwjwt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Token struct {
|
||||
Header
|
||||
Claims map[string]interface{}
|
||||
Signature []byte
|
||||
}
|
||||
|
||||
func NewToken() *Token {
|
||||
return &Token{
|
||||
Header: DefaultHeader(),
|
||||
Claims: map[string]interface{}{},
|
||||
}
|
||||
}
|
||||
|
||||
func TokenFromString(token string) *Token {
|
||||
parts := strings.SplitN(token, ".", 2)
|
||||
if len(parts) != 3 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var header Header
|
||||
headerData, _ := base64.RawURLEncoding.DecodeString(parts[0])
|
||||
json.Unmarshal(headerData, &header)
|
||||
|
||||
var claims map[string]interface{}
|
||||
claimsData, _ := base64.RawURLEncoding.DecodeString(parts[1])
|
||||
json.Unmarshal(claimsData, &claims)
|
||||
|
||||
signature, _ := base64.RawURLEncoding.DecodeString(parts[2])
|
||||
|
||||
return &Token{
|
||||
Header: header,
|
||||
Claims: claims,
|
||||
Signature: signature,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Token) Sign(secret []byte) {
|
||||
t.Signature = t.sign(secret)
|
||||
}
|
||||
|
||||
func (t *Token) Verify(secret []byte) bool {
|
||||
if exp, has := t.Claims[Expiry]; has {
|
||||
if int64(exp.(float64)) < time.Now().Unix() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if iat, has := t.Claims[IssuedAt]; has {
|
||||
if int64(iat.(float64)) > time.Now().Unix() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if nbf, has := t.Claims[NotBefore]; has {
|
||||
if int64(nbf.(float64)) > time.Now().Unix() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
newSignature := t.sign(secret)
|
||||
return bytes.Equal(newSignature, t.Signature)
|
||||
}
|
||||
|
||||
func (t Token) String() string {
|
||||
buf := new(bytes.Buffer)
|
||||
be := base64.NewEncoder(base64.RawURLEncoding, buf)
|
||||
|
||||
headerData, _ := json.Marshal(t.Header)
|
||||
be.Write(headerData)
|
||||
buf.WriteByte('.')
|
||||
|
||||
claimsData, _ := json.Marshal(t.Claims)
|
||||
be.Write(claimsData)
|
||||
buf.WriteByte('.')
|
||||
|
||||
be.Write(t.Signature)
|
||||
be.Close()
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (t Token) sign(secret []byte) []byte {
|
||||
buf := new(bytes.Buffer)
|
||||
be := base64.NewEncoder(base64.RawURLEncoding, buf)
|
||||
|
||||
headerData, _ := json.Marshal(t.Header)
|
||||
be.Write(headerData)
|
||||
buf.WriteByte('.')
|
||||
|
||||
claimsData, _ := json.Marshal(t.Claims)
|
||||
be.Write(claimsData)
|
||||
be.Close()
|
||||
|
||||
mac := hmac.New(sha256.New, secret)
|
||||
mac.Write(buf.Bytes())
|
||||
return mac.Sum(nil)
|
||||
}
|
Loading…
Reference in new issue