Bu örnekte ECDSA anahtarları oluşturacağız, ardından JWT belirtecini kullanıp imzalayıp doğrulayacağız. Normalde özel anahtarı güvenli bir yere kaydedersiniz ve uygulamanızda kullanmak üzere her iki anahtar nesneyi yeniden oluşturmak için yeniden kullanırsınız. Tam ECDSA örneğini burada bulabilirsiniz.


JWT


package jwt

type Token struct {
ID string
ClientID string
}

package jwt

import "time"

type CreateTokenArgs struct {
ID string
ClientID string
Now time.Time
TTL time.Duration
}

type ValidateToken struct {
Token string
}

package jwt

import (
"context"
"errors"

"github.com/golang-jwt/jwt/v5"
)

type JWT struct {
Issuer string
SigningMethod jwt.SigningMethod
PublicKey any
PrivateKey any
}

func (j *JWT) CreateToken(ctx context.Context, args CreateTokenArgs) (string, error) {
token := jwt.NewWithClaims(j.SigningMethod, jwt.RegisteredClaims{
ID: args.ID,
Subject: args.ClientID,
Issuer: j.Issuer,
ExpiresAt: jwt.NewNumericDate(args.Now.Add(args.TTL)),
NotBefore: jwt.NewNumericDate(args.Now),
IssuedAt: jwt.NewNumericDate(args.Now),
})

sig, err := token.SignedString(j.PrivateKey)
if err != nil {
return "", err
}

return sig, nil
}

func (j *JWT) ValidateToken(ctx context.Context, args ValidateToken) (Token, error) {
token, err := jwt.ParseWithClaims(args.Token, &jwt.RegisteredClaims{}, func(t *jwt.Token) (interface{}, error) {
return j.PublicKey, nil
})
if err != nil {
return Token{}, err
}

if !token.Valid {
return Token{}, errors.New("invalid token")
}

claims, ok := token.Claims.(*jwt.RegisteredClaims)
if !ok {
return Token{}, errors.New("invalid token claims")
}

return Token{
ID: claims.ID,
ClientID: claims.Subject,
}, nil
}

ECDSA


package ecdsa

import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
)

type ECDSA struct {
Private *ecdsa.PrivateKey
Public *ecdsa.PublicKey
}

func New(curve elliptic.Curve) (ECDSA, error) {
prv, err := ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
return ECDSA{}, err
}

return ECDSA{
Private: prv,
Public: &prv.PublicKey,
}, nil
}

main.go


package main

import (
"context"
"crypto/elliptic"
"fmt"
"time"

ecdsapkg "rate-limit/pkg/ecdsa"

jwtpkg "rate-limit/pkg/jwt"

jwtv5 "github.com/golang-jwt/jwt/v5"
)

func main() {
ecdsa, err := ecdsapkg.New(elliptic.P256())
if err != nil {
panic(err)
}

jwt := jwtpkg.JWT{
Issuer: "inanzzz",
SigningMethod: jwtv5.SigningMethodES256,
PublicKey: ecdsa.Public,
PrivateKey: ecdsa.Private,
}

tokenString, err := jwt.CreateToken(context.Background(), jwtpkg.CreateTokenArgs{
ID: "token-id-1",
ClientID: "client-id-1",
Now: time.Now().UTC(),
TTL: time.Hour,
})
if err != nil {
panic(err)
}

fmt.Println("TOKEN STRING:")
fmt.Println(tokenString)

tokenObject, err := jwt.ValidateToken(context.Background(), jwtpkg.ValidateToken{Token: tokenString})
if err != nil {
panic(err)
}

fmt.Println("TOKEN OBJECT:")
fmt.Printf("%+v\n", tokenObject)
}

Test


$ go run -race main.go

TOKEN STRING:
eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJpbmFuenp6Iiwic3ViIjoiY2xpZW50LWlkLTEiLCJleHAiOjE3MDY2MzUxNjUsIm5iZiI6MTcwNjYzMTU2NSwiaWF0IjoxNzA2NjMxNTY1LCJqdGkiOiJ0b2tlbi1pZC0xIn0.PNsehlztU3LCG9boo9PA8iMsGr264xtMe7wuBbcZgilFIvQsUJulJ6d0lzf1b9fUxayy8gmeqIz8XLjv6b63Cg

TOKEN OBJECT:
{ID:token-id-1 ClientID:client-id-1}

İçerik


# HEADER

{
"alg": "ES256",
"typ": "JWT"
}

# PAYLOAD

{
"iss": "inanzzz",
"sub": "client-id-1",
"exp": 1706635165,
"nbf": 1706631565,
"iat": 1706631565,
"jti": "token-id-1"
}