google_oauth/
lib.rs

1//! # Google-Oauth
2//!
3//! ## Description
4//! `Google-Oauth` is a server-side verification library for Google oauth2.
5//!
6//! `Google-Oauth` can help you to verify `id_token` or `access_token` which is generated from Google.
7//!
8//! ## Usage (async)
9//!
10//! ### 1. Setup
11//! To import `Google-Oauth` to your project, please add this line into your `Cargo.toml`.
12//!
13//! ```toml
14//! [dependencies]
15//! google-oauth = { version = "1" }
16//! ```
17//!
18//! If you decided to use `async` function, please select an `async` runtime. Here are some options for you:
19//! 1. [tokio](https://github.com/tokio-rs/tokio)
20//! 2. [async-std](https://github.com/async-rs/async-std)
21//! 3. [actix-web](https://github.com/actix/actix-web)
22//!
23//! We use [tokio](https://github.com/tokio-rs/tokio) in our example, and refactor our main function like this:
24//! ```rust
25//! #[tokio::main]
26//! // #[async_std::main] // when you use [async-std]
27//! // #[actix_web::main] // when you use [actix-web]
28//! async fn main() {}
29//! ```
30//!
31//! ### 2. Do Verification (`id_token`)
32//!
33//! You can get your `client_id` from Google Admin Console (or somewhere else), and an `id_token` has been provided from
34//! your user. They are all `string-like`. Use the following code to do verification:
35//! ```rust
36//! use google_oauth::AsyncClient;
37//!
38//! #[tokio::main]
39//! async fn main() {
40//!     let client_id = "your client id";
41//!     let id_token = "the id_token";
42//!
43//!     let client = AsyncClient::new(client_id);
44//!     /// or, if you want to set the default timeout for fetching certificates from Google, e.g, 30 seconds, you can:
45//!     /// ```rust
46//!     /// let client = AsyncClient::new(client_id).timeout(time::Duration::from_sec(30));
47//!     /// ```
48//!
49//!     let payload = client.validate_id_token(id_token).await.unwrap(); // In production, remember to handle this error.
50//!
51//!     // When we get the payload, that mean the id_token is valid.
52//!     // Usually we use `sub` as the identifier for our user...
53//!     println!("Hello, I am {}", &payload.sub);
54//! }
55//! ```
56//! 
57//! **Do verification without any client id**
58//! 
59//! When no `client_id` is provided for `AsyncClient`, `cliend_id` will not be used when validating `id_token`.
60//! In this case, `AsyncClient` will accept all `client_id`.
61//! However, Google issuer (`iss`), expiration (`exp`) and JWT hash **CAN NOT** be skipped.
62//!
63//! ### 3. Do Verification (`AccessToken`)
64//!
65//! Sometimes, Google will return an `access_token` instead of `id_token`. `Google-Oauth` still provides API for validate
66//! `access_token` from Google.
67//!
68//! Note: when validating `access_token`, we don't matter the `client_id`. So if you just need to validate `access_token`,
69//! you can simply pass an empty `client_id`, just like this:
70//!
71//! ```rust
72//! use google_oauth::AsyncClient;
73//!
74//! #[tokio::main]
75//! async fn main() {
76//!     let access_token = "the access_token";
77//!
78//!     let client = AsyncClient::new("");
79//!
80//!     let payload = client.validate_access_token(access_token).await.unwrap(); // In production, remember to handle this error.
81//!
82//!     // When we get the payload, that mean the id_token is valid.
83//!     // Usually we use `sub` as the identifier for our user...
84//!     println!("Hello, I am {}", &payload.sub);
85//! }
86//! ```
87//!
88//! Warning: the result of `access_token` is different from the result of `id_token`, although they have a same field `sub`.
89//!
90//! > For full example, please view ./example/async_client/
91//!
92//! ## Algorithm Supported
93//! For validating `id_token`, Google may use these two kinds of hash algorithm to generate JWTs:
94//!
95//! - [x] RS256
96//! - [ ] ES256
97//!
98//! However, I cannot find any approach to get a valid `ES256` token, and as a result, I remained a `unimplemented` branch,
99//! and return an `Err` if the JWT is `ES256` hashed.
100//!
101//! Feel free to create a new issue if you have an example. PR is welcome.
102//!
103//! ## Usage (blocking)
104//! `Google-Oauth` also provides a blocking client. You need to enable `blocking` feature:
105//! ```toml
106//! [dependencies]
107//! google-oauth = { version = "1", features = ["blocking"] }
108//! ```
109//!
110//! You can use `google_oauth::Client` to validate tokens:
111//! ```rust
112//!     use google_oauth::Client;
113//!
114//!     let client_id = "your client id";
115//!     let id_token = "the id_token";
116//!
117//!     let client = Client::new(client_id);
118//!
119//!     let payload = client.validate_id_token(id_token).unwrap();
120//!
121//!     println!("Hello, I am {}", &payload.sub);
122//! ```
123//!
124//! > For full example, please view ./examples/blocking/
125//!
126//! ## Error Handling
127//!
128//! Most APIs return an `Result<T, E>`, where `E` is [`Error`].
129//! See [`Error`] for more information.
130//!
131//! ## WebAssembly (wasm)
132//! `Google-Oauth` supports wasm, feature `wasm` is required.
133//! ```toml
134//! [dependencies]
135//! google-oauth = { version = "1", features = ["wasm"] }
136//! ```
137//!
138//! You can build this library with ``wasm-pack build --features wasm``. (`cargo install wasm-pack` to install first.)
139//!
140//! If you need to import `wasm` into your project, you can use `google_oauth::Client` to run async functions.
141//!
142//! ## Features
143//! + `default`: enable `AsyncClient`.
144//! + `blocking`: enable `Client`.
145//! + `wasm`: disable `AsyncClient` and `Client`(`blocking`), enable `Client` (`wasm`).
146//! + `reqwest-rustls`: use rustls as the TLS backend of the Reqwest client
147//!
148
149#[cfg(feature = "blocking")]
150mod client;
151#[cfg(not(feature = "wasm"))]
152mod async_client;
153mod output;
154
155#[cfg(feature = "wasm")]
156mod wasm;
157
158mod jwt_parser;
159mod certs;
160mod validate;
161mod utils;
162mod error;
163
164#[cfg(feature = "blocking")]
165pub use client::*;
166#[cfg(not(feature = "wasm"))]
167pub use async_client::*;
168pub use certs::*;
169pub use output::*;
170pub use error::*;
171
172type MyResult<T> = error::Result<T>;
173
174#[cfg(feature = "wasm")]
175pub use wasm::*;
176
177#[allow(unused)]
178const GOOGLE_SA_CERTS_URL: &str = "https://www.googleapis.com/oauth2/v3/certs";
179#[allow(unused)]
180const GOOGLE_ISS: [&str; 2] = ["https://accounts.google.com", "accounts.google.com"];
181#[allow(unused)]
182const DEFAULT_TIMEOUT: u64 = 5u64;
183#[allow(unused)]
184const GOOGLE_OAUTH_V3_USER_INFO_API: &str = "https://www.googleapis.com/oauth2/v3/userinfo";
185
186#[cfg(all(feature = "wasm", feature = "blocking"))]
187compile_error!("wasm and blocking are mutually exclusive and cannot be enabled together");