| Crates.io | oauth2_login |
| lib.rs | oauth2_login |
| version | 0.1.0 |
| created_at | 2025-01-17 23:54:16.09229+00 |
| updated_at | 2025-01-17 23:54:16.09229+00 |
| description | Oauth2 login |
| homepage | |
| repository | https://github.com/0Itsuki0/rust_oauth2_login |
| max_upload_size | |
| id | 1521217 |
| size | 7,371,631 |
This library aims at helping CLI tools in using OAuth2 for user authorization.
pub async fn request_token(
basic_client: &oauth2::basic::BasicClient,
options: RequestTokenOptions) ->
Result<StandardTokenResponse<EmptyExtraTokenFields, BasicTokenType>, RequestTokenError>
This function will
Prompt the user to login with the consent screen
Start a server temporarily for handling the OAuth 2.0 server response
Retreive and return the Access Token upon success
Stop the server upon sucess or User cancelling the Login by closing the consent screen tab
basic_client: oauth2::basic::BasicClient. If redirect_uri is not defined on the client, a redirect_uri of format "http://{host}:{port}/{path}" will be set. The redirect_uri should be an exact match to that set up on the OAuth provider side.
options: RequestTokenOptions. Options for configuring authorizaion scopes, server, and browser while requesting for token. Default values provided.
pub struct RequestTokenOptions {
#[builder(default = "3000")]
pub port: u16,
#[builder(default = r#""localhost".to_string()"#)]
pub host: String,
#[builder(default = r#""/auth/google_callback".to_string()"#)]
pub redirect_path: String,
#[builder(default = "vec![]")]
pub scopes: Vec<String>,
#[builder(default = "None")]
pub browser_window_size: Option<(u32, u32)>,
#[builder(default = "Duration::from_secs(30)")]
pub idle_browser_timeout: Duration,
}
It uses the following crates internally.
oauth2 for token introspection
axum for handling OAuth server reponses
headless_chrome for browser manipulation
Create a project in the Google Cloud Console
Enable APIs for the project from the API Library
Set up the OAuth Consent Screen with the scopes needed.
Create an OAuth client ID from the Credentials page.
Obtain the Client Id and Client Secret creating the credentials
use std::{error::Error, thread, time::Duration};
use oauth2::{basic::BasicClient, AuthUrl, ClientId, ClientSecret, TokenResponse, TokenUrl};
use oauth2_login::{request_token, RequestTokenOptions};
use serde::{Deserialize, Serialize};
const CLIENT_ID: &str = "OAUTH_CLIENT_ID";
const CLIENT_SECRET: &str = "OAUTH_CLIENT_SECRET";
const BASE_AUTH_URL: &str = "https://accounts.google.com/o/oauth2/v2/auth";
const TOKEN_URL: &str = "https://www.googleapis.com/oauth2/v3/token";
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let client = BasicClient::new(
ClientId::new(CLIENT_ID.to_owned()),
Some(ClientSecret::new(CLIENT_SECRET.to_owned())),
AuthUrl::new(BASE_AUTH_URL.to_string())?,
Some(TokenUrl::new(TOKEN_URL.to_string())?)
);
let options = RequestTokenOptions{
port: 3000,
host: "localhost".to_string(),
redirect_path: "/auth/google_callback".to_string(),
scopes: vec!["openid".to_string(), "email".to_string(), "profile".to_string()],
..Default::default()
};
let token = match request_token(&client, options).await {
Ok(token) => token,
Err(e) => {
println!("error: {}", e.to_string());
return Ok(())
},
};
println!("request token: {:?}", token);
let user_info = get_profile(token.access_token().secret()).await?;
println!("Hey {}! Thank you for Login!", user_info.name);
thread::sleep(Duration::from_millis(2000));
Ok(())
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct UserInfo {
email: String,
name: String,
sub: String
}
async fn get_profile(access_token: &str) -> Result<UserInfo, Box<dyn Error>> {
let client = reqwest::Client::new();
let response = client
.get("https://openidconnect.googleapis.com/v1/userinfo")
.bearer_auth(access_token.to_owned())
.send()
.await?;
let user_info = response.json::<UserInfo>().await?;
Ok(user_info)
}
