Vlang:JWT

module main

import crypto.hmac
import crypto.sha256
import encoding.base64
import json
import x.json2
import time

// JWT header fixed to use HS256 algorithm
const header = base64.url_encode_str(json.encode({
  "alg":"HS256"
  "typ":"JWT"
}))

// Generate token
fn generate(secret string, payload map[string]Any) string {
  playload_64 := base64.url_encode_str(json.encode(payload))

  message := '${header}.${playload_64}'
  signature := hmac.new(secret.bytes(), message.bytes(), sha256.sum, 0)
  base64_signature := base64.url_encode_str(signature.bytestr())
  return '${header}.${playload_64}.${base64_signature}'
}

fn main() {
  secret := '46546456'

  payload := {
    // Standard Claims https://datatracker.ietf.org/doc/html/rfc7519#section-4.1
    "iss": Any("your-app-name"),         // Issuer
    "sub": "user123",               // Subject (unique user identifier)
    "aud": ["api-service", "webapp"], // Audience (can be array or string)
    "exp": I64(time.now().add_days(30).unix()),  // Expiration Time (30 days from now)
    "nbf": I64(time.now().unix()),       // Not Before (valid immediately)
    "iat": I64(time.now().unix()),       // Issued At
    "jti": "unique-jwt-id-123",     // JWT ID (prevent replay attacks)

    // Custom Claims
    "name": "Jengro",               // User's name
    "roles": ["admin", "editor"],   // User roles
    "status": "active",             // User status
    "meta": {                       // Nested object
       "login_ip": "192.168.1.100",
       "device_id": "device-xyz"
     }
  }

  token := generate(secret, payload)
  // println(token)

  // verify(secret, token)
  bj := verify(secret, token)
  println(bj)
}

// Verify token
fn verify(secret string, token string) bool {
  // Verify token length
  parts := token.split('.')
  if parts.len != 3 {
      return false
  }

  // Verify Header

  // Verify signature
  message := '${parts[0]}.${parts[1]}'
  signature := hmac.new(secret.bytes(), message.bytes(), sha256.sum, 0)
  expected_sig := base64.url_encode_str(signature.bytestr())
  if parts[2] != expected_sig {
    return false
  }

  // Verify time validity
  // dump(parts[1])
  payload_json := base64.url_decode_str(parts[1])
  payload := json2.decode[Payload](payload_json.str()) or {return false}
  dump(payload)
  now := time.now().unix()
  if now > payload.exp || now < payload.nbf {
      return false
  }

  return true
}

struct Header {
    alg string
    typ string
}

struct Payload {
    // Standard claims
    iss string
    sub string
    aud []string
    exp i64
    nbf i64
    iat i64
    jti string
    // Custom claims
    name   string
    roles  []string
    status string
    meta   map[string]string
}

type F64 = f64
type I64 = i64
type Any = string
    | []string
    | int
    | []int
    | I64
    | []f64
    | F64
    | bool
    | time.Time
    | map[string]int
    | map[string]string
    | []map[string]string
    | []map[string]Any
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容