عميل OAuth لـ Rust: مكتبة oauth2-rs

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مكتبة oauth2-rs: تنفيذ OAuth 2.0 على Rust

\n\n

في تطوير الويب الحديث، OAuth 2.0 هو البروتوكول القياسي لتفويض الوصول. توفر مكتبة oauth2-rs تنفيذًا كاملاً لعميل OAuth 2.0 بلغة Rust. تتيح دمج المصادقة عبر الخدمات الشائعة: Google وGitHub وYandex وVK وغيرها.

\n\n

تدعم هذه المكتبة جميع التدفقات (flows) الرئيسية: Authorization Code وClient Credentials وImplicit بالإضافة إلى Refresh Token. يتم إيلاء اهتمام خاص للأمان: استخدام PKCE (Proof Key for Code Exchange) للعملاء العموميين والتحقق الإلزامي من الرموز المميزة.

\n\n

تثبيت oauth2-rs

\n\n

أضف التبعية في Cargo.toml:

\n\n
[dependencies]\noauth2 = "4.4"\ntokio = { version = "1", features = ["full"] }\nreqwest = { version = "0.11", features = ["json"] }\nserde = { version = "1.0", features = ["derive"] }
\n\n

ستحتاج أيضًا إلى عميل HTTP (يُوصى باستخدام reqwest مع دعم async) ومُسلسل serde للعمل مع JSON.

\n\n

الإعداد الأساسي لعميل OAuth

\n\n

لننظر إلى مثال لـ Google OAuth 2.0. أولاً، سننشئ التهيئة:

\n\n
use oauth2::{\n    AuthorizationCode, AuthUrl, ClientId, ClientSecret, \n    RedirectUrl, TokenUrl, CsrfToken, Scope,\n    basic::BasicClient, TokenResponse\n};\n\nlet client_id = ClientId::new("YOUR_GOOGLE_CLIENT_ID".to_string());\nlet client_secret = ClientSecret::new("YOUR_GOOGLE_CLIENT_SECRET".to_string());\nlet auth_url = AuthUrl::new("https://accounts.google.com/o/oauth2/v2/auth".to_string())\n    .expect("Invalid auth URL");\nlet token_url = TokenUrl::new("https://oauth2.googleapis.com/token".to_string())\n    .expect("Invalid token URL");\n\nlet client = BasicClient::new(\n    client_id,\n    Some(client_secret),\n    auth_url,\n    Some(token_url)\n).set_redirect_uri(\n    RedirectUrl::new("http://localhost:8080/callback".to_string())\n        .expect("Invalid redirect URL")\n);
\n\n

إنشاء رابط التفويض

\n\n

ننشئ رابطًا يجب توجيه المستخدم إليه:

\n\n
let (auth_url, csrf_token) = client\n    .authorize_url(CsrfToken::new_random)\n    .add_scope(Scope::new("openid".to_string()))\n    .add_scope(Scope::new("email".to_string()))\n    .url();\n\nprintln!("انتقل إلى الرابط: {}", auth_url);\n// احفظ csrf_token للتحقق عند الاستدعاء
\n\n

يحمي CsrfToken من هجمات تزوير الطلبات عبر المواقع (CSRF). يجب حفظه مؤقتًا (مثلًا في الجلسة أو الكوكيز) والتحقق منه عند معالجة الاستدعاء.

\n\n

معالجة الاستدعاء والحصول على الرمز المميز

\n\n

بعد أن يؤكد المستخدم الوصول، سيعيد التوجيه إلى redirect_uri مع معامل code. مثال على معالج في Rust:

\n\n
use actix_web::{web, HttpRequest, HttpResponse};\nuse oauth2::AuthorizationCode;\n\nasync fn callback(query: web::Query<std::collections::HashMap<String, String>>) -> HttpResponse {\n    let code = query.get("code")\n        .expect("Missing authorization code");\n    let state = query.get("state")\n        .expect("Missing state");\n\n    // تحقق من state مقابل csrf_token المحفوظ\n    // ...\n\n    let token_result = client\n        .exchange_code(AuthorizationCode::new(code.clone()))\n        .request_async(&reqwest::Client::new())\n        .await;\n\n    match token_result {\n        Ok(token) => {\n            let access_token = token.access_token().secret();\n            let refresh_token = token.refresh_token()\n                .map(|rt| rt.secret().clone());\n            // احفظ الرموز المميزة في قاعدة البيانات أو الجلسة\n            HttpResponse::Ok().body("تم التفويض بنجاح!")\n        },\n        Err(e) => {\n            eprintln!("خطأ في تبادل الكود: {:?}", e);\n            HttpResponse::InternalServer                    

توصيات