diff --git a/examples/axum_server.rs b/examples/axum_server.rs index f8f8b5c..7672a37 100644 --- a/examples/axum_server.rs +++ b/examples/axum_server.rs @@ -28,7 +28,7 @@ use axum_extra::extract::{CookieJar, cookie::Cookie}; use http::StatusCode; use serde::Deserialize; use tiny_google_oidc::{ - code::{AccessType, AdditionalScope, CodeRequest, UnCheckedCodeResponse}, + code::{AccessType, AdditionalScope, CodeRequest, RawCodeResponse}, config::{Config, ConfigBuilder}, csrf_token::CSRFToken, id_token::{IDToken, IDTokenRequest, send_id_token_req}, @@ -127,7 +127,7 @@ async fn call_back( req: Request, ) -> Result { // Construct UnCheckedCodeResponse - let code_res = UnCheckedCodeResponse::from_url(req).map_err(|e| { + let code_res = RawCodeResponse::new(req).map_err(|e| { error!("Failed to parse url: {}", e); StatusCode::INTERNAL_SERVER_ERROR })?; diff --git a/examples/hyper/login_service.rs b/examples/hyper/login_service.rs index 258b26d..28c408c 100644 --- a/examples/hyper/login_service.rs +++ b/examples/hyper/login_service.rs @@ -10,7 +10,7 @@ use http_body_util::{BodyExt, Empty, combinators::BoxBody}; use hyper::body::Incoming; use redis::{aio::ConnectionManager, cmd}; use tiny_google_oidc::{ - code::{AccessType, AdditionalScope, CodeRequest, UnCheckedCodeResponse}, + code::{AccessType, AdditionalScope, CodeRequest, RawCodeResponse}, config::Config, csrf_token::CSRFToken, id_token::{IDToken, IDTokenRequest, send_id_token_req}, @@ -98,7 +98,7 @@ impl LoginService { .await?; // Create UncheckedCodeResponse from url - let code_res = UnCheckedCodeResponse::from_url(&req)?; + let code_res = RawCodeResponse::new(&req)?; // Consume the response and get the code // Verify that the CSRFToken matches (Error if they do not match) let code = code_res.exchange_with_code(&csrf_token)?; diff --git a/src/code.rs b/src/code.rs index c1ab7a6..8642200 100644 --- a/src/code.rs +++ b/src/code.rs @@ -3,7 +3,7 @@ //! //! It provides the following key functionalities: //! - Generating an authorization request URL (`CodeRequest`). -//! - Parsing and verifying the authorization code received from Google's callback (`UnCheckedCodeResponse`). +//! - Parsing and verifying the authorization code received from Google's callback (`RawCodeResponse`). //! //! # Key Structures and Features //! @@ -11,13 +11,13 @@ //! A structure used to generate the authorization request URL. //! - Includes parameters like CSRF token, scope, redirect URI, and nonce. //! -//! ## `UnCheckedCodeResponse` +//! ## `RawCodeResponse` //! Represents the authorization code response received from Google. //! - This response must be validated using a CSRF token before it can be used. //! //! ## `Code` //! Represents a verified authorization code that can be exchanged for tokens. -//! - This is obtained after validating the `UnCheckedCodeResponse` with a CSRF token. +//! - This is obtained after validating the `RawCodeResponse` with a CSRF token. //! //! # Examples //! ## Generating an Authorization Request URL @@ -38,7 +38,7 @@ //! //! ## Handling the Callback and Verifying the Authorization Code //! ```rust,no_run -//! let response = UnCheckedCodeResponse::from_url(req).unwrap(); +//! let response = RawCodeResponse::new(req).unwrap(); //! // get stored CSRF token From DB(Redis, in memory ...) //! let csrf_token = store.get("csrf_token_key")?; //! @@ -48,18 +48,18 @@ //! # Flow //! 1. Generate a CSRF token (`CSRFToken`) and include it in the authorization request. //! 2. Redirect the user to Google's authentication page. -//! 3. After authentication, Google redirects back with an authorization code (`UnCheckedCodeResponse`). -//! 4. Validate the CSRF token in the `UnCheckedCodeResponse` using `Code::new_with_verify_csrf()` or `UnCheckedCodeResponse::exchange_with_code()`. +//! 3. After authentication, Google redirects back with an authorization code (`RawCodeResponse`). +//! 4. Validate the CSRF token in the `RawCodeResponse` using `Code::new_with_verify_csrf()` or `RawCodeResponse::exchange_with_code()`. //! 5. If validation succeeds, a `Code` is obtained, which can be exchanged for tokens. //! //! # Notes //! - Always validate the CSRF token to ensure the integrity of the authentication flow. -//! - Do not use `UnCheckedCodeResponse` directly without verification. +//! - Do not use `RawCodeResponse` directly without verification. use url::Url; use crate::{ config::{AuthEndPoint, ClientID, Config, RedirectURI}, - csrf_token::{CSRFToken, UnCheckedCSRFToken}, + csrf_token::{CSRFToken, RawCSRFToken}, error::Error, nonce::Nonce, }; @@ -77,11 +77,11 @@ use std::{collections::HashMap, iter::Iterator}; /// /// # How to Create /// A `Code` can only be created after validating the `CSRFToken`. -/// Use either `Code::new_with_verify_csrf` or `UnCheckedCodeResponse::exchange_with_code` to validate and create a `Code`. +/// Use either `Code::new_with_verify_csrf` or `RawCodeResponse::exchange_with_code` to validate and create a `Code`. /// /// # Example /// ```rust,no_run -/// let response = UnCheckedCodeResponse::from_url("https://example.com/callback?...").unwrap(); +/// let response = RawCodeResponse::new(req).unwrap(); /// let csrf_token = store.get("csrf_token_key")?; /// /// let code = response.exchange_with_code(csrf_token).expect("CSRF token mismatch!"); @@ -96,10 +96,7 @@ pub struct Code(pub(crate) String); impl Code { /// Checks if `res.state` (CSRF token from Google) matches `csrf_token` (generated by user). /// If valid, returns a `Code`; otherwise, returns `Error::CSRFNotMatch`. - pub fn new_with_verify_csrf( - res: UnCheckedCodeResponse, - csrf_token_val: &str, - ) -> Result { + pub fn new_with_verify_csrf(res: RawCodeResponse, csrf_token_val: &str) -> Result { if res.state.0 == csrf_token_val { Ok(res.code) } else { @@ -208,26 +205,26 @@ impl<'a> CodeRequest<'a> { /// Must be validated using a CSRF token before use. /// # Example /// ```rust,no_run -/// let response = UnCheckedCodeResponse::from_url(req).unwrap(); +/// let response = RawCodeResponse::new(req).unwrap(); /// let csrf_token = store.get("csrf_token_key")?; /// /// let code = response.exchange_with_code(csrf_token).expect("CSRF token mismatch!"); /// ``` #[derive(Debug, Clone)] -pub struct UnCheckedCodeResponse { - state: UnCheckedCSRFToken, +pub struct RawCodeResponse { + state: RawCSRFToken, code: Code, } -impl UnCheckedCodeResponse { - pub fn from_url(query_src: Q) -> Result +impl RawCodeResponse { + pub fn new(query_src: Q) -> Result where Q: QueryExtractor, { let query_str = query_src.extract_query().ok_or(Error::ParamsNotFound)?; let params: HashMap<_, _> = url::form_urlencoded::parse(query_str.as_bytes()).collect(); Ok(Self { - state: UnCheckedCSRFToken( + state: RawCSRFToken( params .get("state") .ok_or(Error::ParamsNotFound)? @@ -338,7 +335,7 @@ mod tests { use crate::{code::AccessType, config::ConfigBuilder, csrf_token::CSRFToken, nonce::Nonce}; - use super::{AdditionalScope, CodeRequest, UnCheckedCodeResponse}; + use super::{AdditionalScope, CodeRequest, RawCodeResponse}; #[test] fn test_code_req_offline() { @@ -559,12 +556,12 @@ mod tests { let uri = format!("https://www.example.com/autu?code={}&state={}", code, state); let http_req = http::Request::builder().uri(uri).body(()).unwrap(); - let uncheck_code_res = UnCheckedCodeResponse::from_url(http_req); + let raw_code_res = RawCodeResponse::new(http_req); - assert!(uncheck_code_res.is_ok()); + assert!(raw_code_res.is_ok()); - assert_eq!(uncheck_code_res.clone().unwrap().state.0, "mystate"); - assert_eq!(uncheck_code_res.unwrap().code.0, "mycode"); + assert_eq!(raw_code_res.clone().unwrap().state.0, "mystate"); + assert_eq!(raw_code_res.unwrap().code.0, "mycode"); } #[test] @@ -572,8 +569,8 @@ mod tests { let uri = format!("https://www.example.com/"); let http_req = http::Request::builder().uri(uri).body(()).unwrap(); - let uncheck_code_res = UnCheckedCodeResponse::from_url(http_req); + let raw_code_res = RawCodeResponse::new(http_req); - assert!(uncheck_code_res.is_err()); + assert!(raw_code_res.is_err()); } } diff --git a/src/csrf_token.rs b/src/csrf_token.rs index ab008f7..3ee0a6e 100644 --- a/src/csrf_token.rs +++ b/src/csrf_token.rs @@ -45,7 +45,7 @@ impl CSRFToken { /// /// This token **has not been verified yet** and should be checked against the stored `CSRFToken` before proceeding. #[derive(Debug, Clone)] -pub struct UnCheckedCSRFToken(pub(crate) String); +pub struct RawCSRFToken(pub(crate) String); #[cfg(test)] mod tests {