عميل OAuth لـ Rust: مكتبة oauth2
OAuth 2.0 هو المعيار الصناعي لتفويض الوصول. يُستخدم على نطاق واسع لمصادقة المستخدمين عبر خدمات الطرف الثالث (Google، GitHub، Facebook) دون نقل كلمة المرور. في نظام Rust البيئي، واحدة من أشهر المكتبات وأكثرها نضجًا لتطبيق OAuth 2.0 هي oauth2 (crate oauth2). توفر واجهة برمجة تطبيقات آمنة وغير متزامنة ومرنة للعمل مع أي موفري OAuth.
الميزات الرئيسية
- دعم جميع أنواع المنح القياسية: Authorization Code، Client Credentials، Resource Owner Password Credentials، Implicit.
- دعم مدمج لـ PKCE (Proof Key for Code Exchange) لتعزيز أمان العملاء العامين.
- عمل غير متزامن باستخدام
reqwestأوureqفي الخلفية. - أمان الأنواع: جميع الرموز وعناوين URL والمعاملات محددة النوع بدقة، مما يستبعد الأخطاء في مرحلة التجميع.
- إعداد مرن لأي موفر خدمة من خلال تكوين نقاط النهاية والنطاقات (scopes).
- العمل مع الرموز: التحديث التلقائي (refresh)، والتحقق من انتهاء الصلاحية.
التثبيت
أضف التبعية إلى ملف Cargo.toml الخاص بك:
[dependencies]oauth2 = "4.4"tokio = { version = "1", features = ["full"] }serde = { version = "1", features = ["derive"] }reqwest = { version = "0.11", features = ["json"] }مثال أساسي: الترخيص عبر Google
لنستعرض الدورة الكاملة لـ OAuth 2.0 مع منح Authorization Code + PKCE لـ Google:
use oauth2::{ AuthorizationCode, AuthUrl, ClientId, ClientSecret, CsrfToken, PkceCodeChallenge, RedirectUrl, Scope, TokenResponse, TokenUrl,};use oauth2::basic::BasicClient;use oauth2::reqwest::async_http_client;use url::Url;
#[tokio::main]async fn main() -> Result<(), Box> { // 1. إنشاء عميل بإعدادات Google let client = BasicClient::new( ClientId::new("معرف_عميل_Google_الخاص_بك".to_string()), Some(ClientSecret::new("سر_عميل_Google_الخاص_بك".to_string())), AuthUrl::new("https://accounts.google.com/o/oauth2/v2/auth".to_string())?, Some(TokenUrl::new("https://oauth2.googleapis.com/token".to_string())?), ) .set_redirect_uri(RedirectUrl::new("http://localhost:8080/callback".to_string())?);
// 2. إنشاء تحدي PKCE let (pkce_challenge, pkce_verifier) = PkceCodeChallenge::new_random_sha256();
// 3. بناء عنوان URL لترخيص المستخدم let (auth_url, csrf_token) = client .authorize_url(CsrfToken::new_random) .add_scope(Scope::new("openid".to_string())) .add_scope(Scope::new("profile".to_string())) .add_scope(Scope::new("email".to_string())) .set_pkce_challenge(pkce_challenge) .url();
println!("افتح في المتصفح: {}", auth_url);
// 4. (محاكاة) الحصول على رمز الترخيص من المستخدم let code = "الرمز_من_المتصفح_بعد_إعادة_التوجيه";
// 5. استبدال الرمز بالرمز المميز let token_response = client .exchange_code(AuthorizationCode::new(code.to_string())) .set_pkce_verifier(pkce_verifier) .request_async(async_http_client) .await?;
println!("رمز الوصول: {}", token_response.access_token().secret()); println!("رمز التحديث: {:?}", token_response.refresh_token());
Ok(())} سيناريوهات متقدمة
1. تحديث الرمز المميز (Refresh Token)
عند انتهاء صلاحية رمز الوصول، استخدم رمز التحديث للحصول على رمز جديد:
use oauth2::RefreshToken;
let refresh_token = RefreshToken::new("رمز_التحديث_الخاص_بك".to_string());let new_token = client .exchange_refresh_token(&refresh_token) .requ