module main import crypto.hmac import crypto.sha256 import crypto.bcrypt import encoding.base64 import json import databases import time struct JwtHeader { alg string typ string } struct JwtPayload { sub string // (subject) = Entity to whom the token belongs, usually the user ID; iss string // (issuer) = Token issuer; exp string // (expiration) = Timestamp of when the token will expire; iat time.Time // (issued at) = Timestamp of when the token was created; aud string // (audience) = Token recipient, represents the application that will use it. name string roles string permissions string } fn (mut app App) service_auth(username string, password string) !string { mut db := databases.create_db_connection() or { eprintln(err) panic(err) } defer { db.close() or { panic(err) } } users := sql db { select from User where username == username }! user := users.first() if user.username != username { return error('user not found') } if !user.active { return error('user is not active') } bcrypt.compare_hash_and_password(password.bytes(), user.password.bytes()) or { return error('Failed to auth user, ${err}') } token := make_token(user) return token } fn make_token(user User) string { secret := 'SECRET_KEY' // os.getenv('SECRET_KEY') jwt_header := JwtHeader{'HS256', 'JWT'} jwt_payload := JwtPayload{ sub: '${user.id}' name: '${user.username}' iat: time.now() } header := base64.url_encode(json.encode(jwt_header).bytes()) payload := base64.url_encode(json.encode(jwt_payload).bytes()) signature := base64.url_encode(hmac.new(secret.bytes(), '${header}.${payload}'.bytes(), sha256.sum, sha256.block_size).bytestr().bytes()) jwt := '${header}.${payload}.${signature}' return jwt } fn auth_verify(token string) bool { if token == '' { return false } secret := 'SECRET_KEY' // os.getenv('SECRET_KEY') token_split := token.split('.') signature_mirror := hmac.new(secret.bytes(), '${token_split[0]}.${token_split[1]}'.bytes(), sha256.sum, sha256.block_size).bytestr().bytes() signature_from_token := base64.url_decode(token_split[2]) return hmac.equal(signature_from_token, signature_mirror) // return true }