Zpět na domů

Vývoj služby autorizace v Rustu: tokeny, šifrování, Redis

Článek se věnuje vývoji služby autorizace v Rustu, pokrývá generování JWT a opaque tokenů, jejich ověřování pomocí asymetrického šifrování a úložiště v Redis. Materiál obsahuje praktické příklady kódu a diskusi o potenciálních zranitelnostech.

Jak postavit službu autorizace v Rustu: od základů po pokročilé techniky
Advertisement 728x90

Vývoj autorizační služby v Rustu: od tokenů po orchestrace

Vytvoření spolehlivé autorizační služby v Rustu vyžaduje hluboké porozumění kryptografie, správy tokenů a návrhu abstrakcí. Tento materiál rozebírá praktické zkušenosti z vývoje, včetně generování JWT a opaque-tokenů, jejich ověřování a ukládání v Redis.

Architektura tokenů a jejich generování

Služba využívá dva typy tokenů: access (JWT) a refresh (opaque). Access-tokeny zajišťují krátkodobý přístup, zatímco refresh-tokeny slouží k jejich obnovení bez opakované autentizace uživatele.

Pro generování JWT-tokenů se používá asymetrické šifrování s algoritmem RS256. To vyžaduje pár klíčů: soukromý pro podepisování a veřejný pro ověřování. Opaque-tokeny se generují jako náhodné řetězce base64, které nenesou informace pro klienta, což zvyšuje bezpečnost.

Google AdInline article slot

Klíčové komponenty generování

  • JwtTokenProvider: trait pro generování JWT s využitím claims a soukromého klíče.
  • OpaqueTokenProvider: trait pro vytváření nepřehledných tokenů prostřednictvím náhodných bajtů.
  • Struktura claims: zahrnuje standardní pole, jako je sub (identifikátor uživatele), jti (identifikátor tokenu), iat (čas vytvoření) a exp (doba platnosti).

Příklad implementace JwtTokenProvider:

pub trait IJwtTokenProvider {
    type Claims: Send + Sync;
    type Error;
    fn generate(&self, claims: &Self::Claims, pem: &str) -> Result<String, Self::Error>;
}

Ověřování a validace tokenů

Ověřování JWT-tokenů probíhá přes veřejný klíč, což zabraňuje použití kompromitovaných soukromých klíčů. K tomu je implementován trait IJwtTokenValidator, který kontroluje podpis a integritu tokenu.

Specifika validace

  • Využití formátu PEM: klíče jsou uloženy v PEM-souborech, podporujících certifikáty a řetězce důvěry.
  • Šifrovací algoritmy: služba podporuje jak symetrické (např. HSA), tak asymetrické (např. RSA) metody, s preferencí těch asymetrických pro vyšší bezpečnost.
  • Konverze claims: doménové modely claims jsou převedeny pro kompatibilitu s knihovnami, například konverze DateTime na usize.

Příklad kódu pro ověření:

Google AdInline article slot
pub trait IJwtTokenValidator {
    type Claims: Send + Sync;
    type Error;
    fn verify(&self, token: &str, pem: &str) -> Result<Self::Claims, Self::Error>;
}

Ukládání a orchestrace tokenů

Pro správu tokenů a klíčů jsou vyvinuty TokenManager a KeyManager. TokenManager zodpovídá za generování, ověřování a ukládání tokenů v Redis, využívající abstrakce pro flexibilitu.

Implementace RedisIO

Modul RedisIO zjednodušuje práci s úložištěm, poskytuje metody setex, get a delete. To snižuje boilerplate-kód a zlepšuje čitelnost.

Příklad implementace:

Google AdInline article slot
impl<Storage> RedisIO<Storage>
where Storage: redis::AsyncCommands + Send + Sync
{
    pub async fn setex(&mut self, key: &str, data: &str, exp: u64) -> Result<(), redis::RedisError> {
        self.redis_storage.set_ex::<&str, String, (>(&key, data.to_string(), exp).await?;
        Ok(())
    }
}

Funkcionalita TokenManager

TokenManager využívá generické typy pro poskytovatele a validátory, což umožňuje snadnou výměnu komponent. Hlavní metody:

  • generate_pair: vytváří pár access- a refresh-tokenů, ukládá je v Redis se stanovenou dobou života.
  • verify_access: kontroluje platnost access-tokenu a jeho existenci v úložišti.

Příklad použití:

pub async fn generate_pair(&mut self, claims: &Claims, pem: &str) -> Result<(String, String), TokenManagerError> {
    let access_token = self.access_provider.generate(&claims, &pem)?;
    let refresh_token = self.refresh_provider.generate();
    // Logika uložení v Redis
    Ok((access_token, refresh_token))
}

Co je důležité

  • Použití asymetrického šifrování (RS256) pro JWT zvyšuje bezpečnost oproti symetrickým metodám.
  • Opaque-tokeny jsou generovány jako náhodné řetězce base64, což ztěžuje jejich padělání.
  • Abstrakce prostřednictvím traits umožňují snadné testování a modifikace komponent služby.
  • Ukládání tokenů v Redis s TTL zajišťuje správu session a snižuje zátěž databáze.
  • Správné oddělení soukromých a veřejných klíčů je klíčové pro prevenci zranitelností.

Potenciální problémy a jejich řešení

Během vývoje bylo identifikováno několik zranitelností a obtíží:

  • Růst velikosti base64: při kódování 32 bajtů do base64 se řetězec zvětší na 43 bajtů, což může vést k neočekávaným chybám v logice ukládání.
  • Chyby v správě klíčů: použití soukromého klíče místo veřejného pro ověřování narušuje bezpečnost.
  • Obtíže s datovými typy: konverze mezi DateTime a usize vyžaduje dodatečnou validaci.

Pro jejich odstranění se doporučuje:

  • Testovat hraniční případy s různými velikostmi dat.
  • Implementovat přísné kontroly typů a formátů klíčů.
  • Využívat knihovny s podporou standardů JWT a kryptografie.

— Editorial Team

Advertisement 728x90

Číst dál