Skip to content

Instantly share code, notes, and snippets.

@DavidDeCoding
Last active February 9, 2024 04:43
Show Gist options
  • Save DavidDeCoding/4d8245b20fa91bb371e293e59a543bb5 to your computer and use it in GitHub Desktop.
Save DavidDeCoding/4d8245b20fa91bb371e293e59a543bb5 to your computer and use it in GitHub Desktop.
Golang JWT Token Generation and Validation
package main
import (
"crypto"
"crypto/hmac"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
// "crypto/x509"
"encoding/base64"
"encoding/json"
// "encoding/pem"
"fmt"
"os"
"strings"
"time"
)
type Header struct {
Alg string `json:"alg"`
Typ string `json:"typ"`
Kid string `json:"kid"`
}
type Payload struct {
Sub string `json:"sub"`
Name string `json:"name"`
Iat int64 `json:"iat"`
Exp int64 `json:"exp"`
}
func Base64UrlEncode(bytes []byte) string {
base64String := base64.StdEncoding.EncodeToString(bytes)
base64String = strings.Replace(base64String, "+", "-", -1)
base64String = strings.Replace(base64String, "/", "_", -1)
base64String = strings.Replace(base64String, "=", "", -1)
return base64String
}
func Base64UrlDecode(base64UrlEncodedString string) ([]byte, error) {
data := strings.Replace(base64UrlEncodedString, "-", "+", -1)
data = strings.Replace(data, "_", "/", -1)
switch len(data) % 4 {
case 0:
case 2:
data += "=="
case 3:
data += "="
}
return base64.StdEncoding.DecodeString(data)
}
func main() {
encryptionType := "RSA256" // "HSA256"
var secret []byte
var privateKey *rsa.PrivateKey
header := Header{
Alg: encryptionType,
Typ: "JWT",
Kid: "XXXXXXXXXX",
}
payload := Payload{
Sub: "1234567890",
Name: "John Doe",
Iat: 1516239022,
Exp: time.Now().Local().Add(time.Hour * 24).Unix(),
}
header_json_encoded_bytes, err := json.Marshal(header)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
payload_json_encoded_bytes, err := json.Marshal(payload)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println("=====================================")
fmt.Println(" Generating the JWT Token ")
fmt.Println("=====================================")
fmt.Print("\n")
fmt.Println("JSON Representation:")
os.Stdout.Write(header_json_encoded_bytes)
os.Stdout.Write([]byte("."))
os.Stdout.Write(payload_json_encoded_bytes)
header_base64_encoded_string := Base64UrlEncode(header_json_encoded_bytes)
payload_base64_encoded_string := Base64UrlEncode(payload_json_encoded_bytes)
signature_string := header_base64_encoded_string + "." + payload_base64_encoded_string
fmt.Print("\n")
fmt.Print("\n")
fmt.Println("Base64 Representation:")
fmt.Print(header_base64_encoded_string)
fmt.Print(".")
fmt.Print(payload_base64_encoded_string)
fmt.Print("\n")
fmt.Print("\n")
signature_base64_encoded_string := ""
switch encryptionType {
case "RSA256":
privateKey, err = rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
hashed := sha256.Sum256([]byte(signature_string))
signature_rsa_bytes, err := rsa.SignPKCS1v15(nil, privateKey, crypto.SHA256, hashed[:])
if err != nil {
fmt.Println(err)
os.Exit(1)
}
signature_base64_encoded_string = Base64UrlEncode(signature_rsa_bytes)
case "HSA256":
secret = make([]byte, 32)
_, err = rand.Read(secret)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Print("\n")
fmt.Print("\n")
fmt.Println("Secret:")
fmt.Print(Base64UrlEncode(secret))
hash := hmac.New(sha256.New, secret)
hash.Write([]byte(signature_string))
signature_hmac_bytes := hash.Sum(nil)
signature_base64_encoded_string = Base64UrlEncode(signature_hmac_bytes)
default:
signature_base64_encoded_string = ""
}
fmt.Print("\n")
fmt.Print("\n")
fmt.Println("Signature Representation:")
fmt.Print(signature_base64_encoded_string)
token := header_base64_encoded_string + "." + payload_base64_encoded_string + "." + signature_base64_encoded_string
fmt.Print("\n")
fmt.Print("\n")
fmt.Println("Token:")
fmt.Print(token)
fmt.Print("\n")
fmt.Print("\n")
fmt.Println("=====================================")
fmt.Println(" Verifying the JWT Token ")
fmt.Println("=====================================")
fmt.Print("\n")
fmt.Print("\n")
token_parts := strings.Split(token, ".")
if len(token_parts) != 3 {
panic("Invalid token")
}
header_json_encoded_bytes, err = Base64UrlDecode(token_parts[0])
if err != nil {
fmt.Printf("Invalid Header: %s", token_parts[0])
os.Exit(1)
}
payload_json_encoded_bytes, err = Base64UrlDecode(token_parts[1])
if err != nil {
fmt.Printf("Invalid Payload: %s", token_parts[1])
os.Exit(1)
}
signature_base64_encoded_string_original := token_parts[2]
fmt.Println("Original Signature:")
fmt.Println(signature_base64_encoded_string_original)
fmt.Print("\n")
// header_base64_encoded_string = Base64UrlEncode(header_json_encoded_bytes)
header_base64_encoded_string = Base64UrlEncode(header_json_encoded_bytes)
payload_base64_encoded_string = Base64UrlEncode(payload_json_encoded_bytes)
signature_string = header_base64_encoded_string + "." + payload_base64_encoded_string
signature_base64_encoded_string_calculated := ""
switch encryptionType {
case "RSA256":
hashed := sha256.Sum256([]byte(signature_string))
signature, err := Base64UrlDecode(signature_base64_encoded_string_original)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
err = rsa.VerifyPKCS1v15(&privateKey.PublicKey, crypto.SHA256, hashed[:], signature)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println("Valid Signature Found")
case "HSA256":
hash := hmac.New(sha256.New, secret)
hash.Write([]byte(signature_string))
signature_hmac_bytes := hash.Sum(nil)
signature_base64_encoded_string_calculated = Base64UrlEncode(signature_hmac_bytes)
fmt.Println("Calculated Signature:")
fmt.Println(signature_base64_encoded_string_calculated)
fmt.Print("\n")
if signature_base64_encoded_string_calculated != signature_base64_encoded_string_original {
fmt.Println("Invalid Signature Found")
os.Exit(1)
}
fmt.Println("Valid Signature Found")
default:
signature_base64_encoded_string_calculated = ""
}
fmt.Println("=====================================")
fmt.Println(" Checking Expiration the JWT Token ")
fmt.Println("=====================================")
fmt.Print("\n")
fmt.Print("\n")
var payload_decoded Payload
json.Unmarshal(payload_json_encoded_bytes, &payload_decoded)
if payload_decoded.Exp < time.Now().Unix() {
fmt.Println("Token Expired")
os.Exit(1)
}
fmt.Println("Token Valid")
fmt.Println("=====================================")
fmt.Println(" To Validate in jwt.io ")
fmt.Println("=====================================")
fmt.Print("\n")
fmt.Print("\n")
fmt.Println("Go to: https://jwt.io/#:~:text=SEE%20JWT%20LIBRARIES-,Debugger,-Warning%3A%20JWTs")
fmt.Printf("\nEnter the token: \n%s\n", token)
switch encryptionType {
case "RSA256":
// pem.Encode(os.Stdout, publicBlock)
// fmt.Printf("\nAdd the `Private Key`: \n")
// var privateKey = &pem.Block{
// Type: "RSA PRIVATE KEY",
// Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
// }
// pem.Encode(os.Stdout, privateKey)
case "HSA256":
fmt.Printf("\nAdd the secret in `Verify Signature`: \n%s\n", Base64UrlEncode(secret))
default:
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment