ys memos

Blog

Rustで簡単なJWTライブラリを実装してみた ~7. Test~


rust

2024/08/31


  1. 概要と使用例
  2. プロジェクト設定
  3. base64関連
  4. 署名アルゴリズム関連
  5. ヘッダ定義
  6. JWT本体の実装
  7. JWT本体のTest

本Partでは、JWT本体のテストを行う。

Jwt構造体はライブラリ本体であり、大きくなりがちだと考え、ファイル分割してtestを書いた。


src/jwt/tests.rs
use serde::{Deserialize, Serialize};

use crate::error::Result;

use super::Jwt;

// Define for Testing
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TestPayload {
    sub: String,
    name: String,
    iat: u64,
}
pub type TestJwt = Jwt<TestPayload>;

const VALID_TOKEN: &str = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.mpHl842O7xEZjgQ8CyX8xYLDoEORGVMnAxULkW-u8Ek";
const TAMPERED_TOKEN : &str = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkxIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.mpHl842O7xEZjgQ8CyX8xYLDoEORGVMnAxULkW-u8Ek";
const SECRET: &[u8; 11] = b"test-secret";

#[test]
fn decode_encode() -> Result<()> {
    let jwt = TestJwt::decode(VALID_TOKEN)?;
    let reencoded = jwt.encode()?;
    assert_eq!(VALID_TOKEN, reencoded);
    Ok(())
}

#[test]
fn verify() -> Result<()> {
    let jwt = TestJwt::decode(VALID_TOKEN)?;
    assert!(jwt.verify(SECRET)?);
    assert!(!jwt.verify(b"dummy-secret")?);
    Ok(())
}

#[test]
fn sign() -> Result<()> {
    let mut jwt = TestJwt::decode(VALID_TOKEN)?;
    assert!(jwt.verify(SECRET)?);
    jwt.sign(b"")?;
    assert!(!jwt.verify(SECRET)?);
    jwt.sign(SECRET)?;
    assert!(jwt.verify(SECRET)?);
    Ok(())
}

#[test]
fn tampering() -> Result<()> {
    let mut jwt = TestJwt::decode(TAMPERED_TOKEN)?;
    assert!(!jwt.verify(SECRET)?);
    jwt.sign(b"")?;
    assert!(!jwt.verify(SECRET)?);
    jwt.sign(SECRET)?;
    assert!(jwt.verify(SECRET)?);
    Ok(())
}


use serde::{Deserialize, Serialize};

use crate::error::Result;

use super::Jwt;

// Define for Testing
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TestPayload {
    sub: String,
    name: String,
    iat: u64,
}
pub type TestJwt = Jwt<TestPayload>;

const VALID_TOKEN: &str = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.mpHl842O7xEZjgQ8CyX8xYLDoEORGVMnAxULkW-u8Ek";
const TAMPERED_TOKEN : &str = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkxIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.mpHl842O7xEZjgQ8CyX8xYLDoEORGVMnAxULkW-u8Ek";
const SECRET: &[u8; 11] = b"test-secret";

まずは基本的な用途、トークンをデコードして、そのままエンコードしたときに同じトークンになるかをtestする。

#[test]
fn decode_encode() -> Result<()> {
    let jwt = TestJwt::decode(VALID_TOKEN)?;
    let reencoded = jwt.encode()?;
    assert_eq!(VALID_TOKEN, reencoded);
    Ok(())
}

トークンを検証が成功するか、失敗するかをtestする。

#[test]
fn verify() -> Result<()> {
    let jwt = TestJwt::decode(VALID_TOKEN)?;
    assert!(jwt.verify(SECRET)?);
    assert!(!jwt.verify(b"dummy-secret")?);
    Ok(())
}

ここでは、正常なトークン・シークレットの組から、ニセのシークレットで署名を変更て失敗することのtest、および正常なシークレットで署名を変更して成功することのtestを行っている。

#[test]
fn sign() -> Result<()> {
    let mut jwt = TestJwt::decode(VALID_TOKEN)?;
    assert!(jwt.verify(SECRET)?);
    jwt.sign(b"")?;
    assert!(!jwt.verify(SECRET)?);
    jwt.sign(SECRET)?;
    assert!(jwt.verify(SECRET)?);
    Ok(())
}

改竄耐性のtest。これは、改ざんされたトークンのverifyが失敗することのtestをし、その後に署名を変更して成功することのtestを行っている。

#[test]
fn tampering() -> Result<()> {
    let mut jwt = TestJwt::decode(TAMPERED_TOKEN)?;
    assert!(!jwt.verify(SECRET)?);
    jwt.sign(b"")?;
    assert!(!jwt.verify(SECRET)?);
    jwt.sign(SECRET)?;
    assert!(jwt.verify(SECRET)?);
    Ok(())
}

ここまで完了すると、1. 概要と使用例で記述したmain.rscargo runで動かせるようになります。


関連タグを探す