ys memos

Blog

Rustで簡単なJWTライブラリを実装してみた ~1. 概要と使用例~


rust

2024/08/30


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

RustやJWTを勉強するために、簡単なJWTライブラリを実装してみました。

リポジトリはこちら→https://github.com/ysuzuki19/rust-chibi-jwt/tree48cb525fa71ccae45244d8b57a687ddf30984fab


JWT(JSON Web Token)は、JSON形式で情報を安全にやり取りするための軽量な仕様で、認証や情報の交換に利用されるものとされている。

トークンの構成は、ヘッダ、ペイロード、署名の3つの部分からなり、それぞれBase64エンコードされている。

<header>.<payload>.<signature>

基本的に、実装が崩れない順番を意識してコードを紹介していく。

一部、mod <hoge>や、testでの利用などが、紹介する順番では動かなくなるので、そこは無視して進めてもらうか、コメントアウトして貰えればと思う。


まずは、どんな使い方をするものを作ったのかを紹介しておく。

以下のように、

  • TokenをDecodeしてPayloadを取り出す
  • PayloadをTokenにEncodeする(署名を含む)

といった使い方を想定して作ってみた。

一連の記事を進めていくと、以下のコードを実行できるようになる。

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

use rust_chibi_jwt::{Alg, Jwt};

// Define payload for sample
// `PartialEq` is unnecessary, but it's using for assert_eq! in main
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct Payload {
    sub: String,
    name: String,
    iat: u64,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // dummy token with secret "my-secret"
    let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.EpM5XBzTJZ4J8AfoJEcJrjth8pfH28LWdjLo90sYb9g";
    let secret: &[u8; 9] = b"my-secret";
    let payload = Payload {
        sub: "1234567890".to_string(),
        name: "John Doe".to_string(),
        iat: 1516239022,
    };

    {
        // Decode and Encode
        let jwt = Jwt::<Payload>::decode(token)?;

        assert!(jwt.verify(secret)?);
        assert_eq!(jwt.payload(), &payload);

        let reencoded: String = jwt.encode()?;
        assert_eq!(token, reencoded);

        println!("Jwt Decode/Encode is OK");
    }

    {
        // Sign and Encode
        let mut jwt = Jwt::new(Alg::HS256, payload);
        jwt.sign(secret)?;
        let encoded: String = jwt.encode()?;
        assert_eq!(token, encoded);

        println!("Jwt Sign/Encode is OK");
    }

    Ok(())
}

実行すると、標準出力は以下のようになる。

rust-chibi-jwt $ cargo run
Jwt Decode/Encode is OK
Jwt Sign/Encode is OK

今回は、勉強目的での実装なので、多くの署名アルゴリズムをサポートせず、(サポート対象を追加できる構成で)HS256のみをサポートしている。



実装全体を通して参考にさせていただいたサイトやドキュメントなどです。

関連タグを探す