3个版本
0.1.2 | 2024年5月10日 |
---|---|
0.1.1 | 2024年5月6日 |
0.1.0 | 2024年4月29日 |
308在 身份验证
每月48次下载
20KB
218 行
oauth-axum
这个crate是oauth2库的包装器,但它已经完成了所有提供者的配置,使得在您的Axum项目中实现它变得很容易。目的是添加这个列表中的所有提供者: https://en.wikipedia.org/wiki/List_of_OAuth_providers 那些提供了oauth2。
用法
要使用它,非常简单。只需创建某个提供者的新实例
- CustomProvider
- GithubProvider
- DiscordProvider
- TwitterProvider
- GoogleProvider
- MicrosoftProvider
- FacebookProvider
- SpotifyProvider
在您的项目中,将其传递给 new
函数
-
client_id: 在您的提供者中创建的应用的唯一ID
-
secret_id: 您提供者中的应用中的秘密令牌,此令牌需要从用户那里隐藏
-
redirect_url: 您的后端将接受的来自提供者的URL
如果您使用的是
CustomProvider
,则需要传递 -
auth_url: 用来获取您的应用访问用户账户权限的提供者URL
-
token_url: 用来生成授权令牌的URL
此项目的结构分为两个步骤
1. 生成URL
此步骤将创建一个URL,将用户重定向到提供者以执行您的应用访问用户信息的授权。
此步骤很重要,因为它将生成验证器字段,需要将其保存到某个地方(内存、数据库...),与状态字段一起保存。状态将是您在第二步中获取验证器的ID。
2. 回调URL
用户接受提供者的授权后,它将重定向用户到您在提供者配置中添加的特定URL redirect_url
,并且重要的是要记住,在oauth-axum参数中应设置相同的URL,如果不是相同的URL,将会发生错误。此重定向将包含两个查询参数,CODE和STATE,我们需要从code和verifier字段生成一个令牌,这也是为什么在第一步中需要将验证器和状态一起保存。之后,您将拥有一个令牌来访问提供者的API。
示例
此方法适用于将在Axum的唯一实例中运行的小型项目。它将状态和验证器保存在内存中,可以在回调URL调用中访问。
mod utils;
use std::sync::Arc;
use axum::extract::Query;
use axum::Router;
use axum::{routing::get, Extension};
use oauth_axum::providers::twitter::TwitterProvider;
use oauth_axum::{CustomProvider, OAuthClient};
use crate::utils::memory_db_util::AxumState;
#[derive(Clone, serde::Deserialize)]
pub struct QueryAxumCallback {
pub code: String,
pub state: String,
}
#[tokio::main]
async fn main() {
dotenv::from_filename("examples/.env").ok();
println!("Starting server...");
let state = Arc::new(AxumState::new());
let app = Router::new()
.route("/", get(create_url))
.route("/api/v1/twitter/callback", get(callback))
.layer(Extension(state.clone()));
println!("🚀 Server started successfully");
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
.await
.unwrap();
axum::serve(listener, app).await.unwrap();
}
fn get_client() -> CustomProvider {
TwitterProvider::new(
std::env::var("TWITTER_CLIENT_ID").expect("TWITTER_CLIENT_ID must be set"),
std::env::var("TWITTER_SECRET").expect("TWITTER_SECRET must be set"),
"https://127.0.0.1:3000/api/v1/twitter/callback".to_string(),
)
}
pub async fn create_url(Extension(state): Extension<Arc<AxumState>>) -> String {
let state_oauth = get_client()
.generate_url(
Vec::from(["users.read".to_string()]),
|state_e| async move {
//SAVE THE DATA IN THE DB OR MEMORY
//state should be your ID
state.set(state_e.state, state_e.verifier);
},
)
.await
.unwrap()
.state
.unwrap();
state_oauth.url_generated.unwrap()
}
pub async fn callback(
Extension(state): Extension<Arc<AxumState>>,
Query(queries): Query<QueryAxumCallback>,
) -> String {
println!("{:?}", state.clone().get_all_items());
// GET DATA FROM DB OR MEMORY
// get data using state as ID
let item = state.get(queries.state.clone());
get_client()
.generate_token(queries.code, item.unwrap())
.await
}
开发下一步
- 添加所有测试
- 添加更多提供者
依赖项
~8–21MB
~320K SLoC