oauth2_google/extensions/
internal_oauth2_v3_user_info_endpoint.rs1use oauth2_client::re_exports::{
2 http::header::{ACCEPT, AUTHORIZATION},
3 serde_json, thiserror, Body, Deserialize, Endpoint, HttpError, Request, Response,
4 SerdeJsonError, Serialize, MIME_APPLICATION_JSON,
5};
6
7pub const URL: &str = "https://www.googleapis.com/oauth2/v3/userinfo";
8
9#[derive(Debug, Clone)]
11pub struct Oauth2V3UserInfoEndpoint {
12 access_token: String,
13}
14impl Oauth2V3UserInfoEndpoint {
15 pub fn new(access_token: impl AsRef<str>) -> Self {
16 Self {
17 access_token: access_token.as_ref().to_owned(),
18 }
19 }
20}
21
22impl Endpoint for Oauth2V3UserInfoEndpoint {
23 type RenderRequestError = Oauth2V3UserInfoEndpointError;
24
25 type ParseResponseOutput = Oauth2V3UserInfo;
26 type ParseResponseError = Oauth2V3UserInfoEndpointError;
27
28 fn render_request(&self) -> Result<Request<Body>, Self::RenderRequestError> {
29 let request = Request::builder()
30 .uri(URL)
31 .header(AUTHORIZATION, format!("Bearer {}", &self.access_token))
32 .header(ACCEPT, MIME_APPLICATION_JSON)
33 .body(vec![])
34 .map_err(Oauth2V3UserInfoEndpointError::MakeRequestFailed)?;
35
36 Ok(request)
37 }
38
39 fn parse_response(
40 &self,
41 response: Response<Body>,
42 ) -> Result<Self::ParseResponseOutput, Self::ParseResponseError> {
43 let body = serde_json::from_slice::<Oauth2V3UserInfo>(response.body())
44 .map_err(Oauth2V3UserInfoEndpointError::DeResponseBodyFailed)?;
45
46 Ok(body)
47 }
48}
49
50#[derive(Deserialize, Serialize, Debug, Clone)]
51pub struct Oauth2V3UserInfo {
52 pub sub: String,
53 pub picture: Option<String>,
54 pub email: Option<String>,
55 pub email_verified: Option<bool>,
56}
57
58#[derive(thiserror::Error, Debug)]
59pub enum Oauth2V3UserInfoEndpointError {
60 #[error("MakeRequestFailed {0}")]
61 MakeRequestFailed(HttpError),
62 #[error("DeResponseBodyFailed {0}")]
64 DeResponseBodyFailed(SerdeJsonError),
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[test]
72 fn de_user_info() {
73 match serde_json::from_str::<Oauth2V3UserInfo>(include_str!(
74 "../../tests/response_body_json_files/oauth2_v3_userinfo.json"
75 )) {
76 Ok(user_info) => {
77 assert_eq!(user_info.sub, "110578243643543721809");
78 }
79 Err(err) => panic!("{err}"),
80 }
81 }
82}