oauth2_google/extensions/
user_info_endpoint.rs1use oauth2_client::{
2 extensions::{EndpointParseResponseError, EndpointRenderRequestError, UserInfo},
3 re_exports::{serde_json, Body, Endpoint, Request, Response},
4};
5
6use super::{
7 internal_oauth2_v3_user_info_endpoint::{
8 Oauth2V3UserInfo, Oauth2V3UserInfoEndpoint, Oauth2V3UserInfoEndpointError,
9 },
10 internal_oidc_v1_userinfo_endpoint::{
11 OidcV1UserInfo, OidcV1UserInfoEndpoint, OidcV1UserInfoEndpointError,
12 },
13};
14
15#[derive(Debug, Clone)]
17pub struct GoogleUserInfoEndpoint {
18 inner: Inner,
19}
20#[derive(Debug, Clone)]
21enum Inner {
22 Oauth2V3UserInfoEndpoint(Oauth2V3UserInfoEndpoint),
23 OidcV1UserInfoEndpoint(OidcV1UserInfoEndpoint),
24}
25impl GoogleUserInfoEndpoint {
26 pub fn new(access_token: impl AsRef<str>, has_openid_scope: bool) -> Self {
27 Self {
28 inner: if has_openid_scope {
29 Inner::OidcV1UserInfoEndpoint(OidcV1UserInfoEndpoint::new(access_token))
30 } else {
31 Inner::Oauth2V3UserInfoEndpoint(Oauth2V3UserInfoEndpoint::new(access_token))
32 },
33 }
34 }
35}
36
37impl Endpoint for GoogleUserInfoEndpoint {
38 type RenderRequestError = EndpointRenderRequestError;
39
40 type ParseResponseOutput = UserInfo;
41 type ParseResponseError = EndpointParseResponseError;
42
43 fn render_request(&self) -> Result<Request<Body>, Self::RenderRequestError> {
44 match &self.inner {
45 Inner::Oauth2V3UserInfoEndpoint(ep) => ep.render_request().map_err(Into::into),
46 Inner::OidcV1UserInfoEndpoint(ep) => ep.render_request().map_err(Into::into),
47 }
48 }
49
50 fn parse_response(
51 &self,
52 response: Response<Body>,
53 ) -> Result<Self::ParseResponseOutput, Self::ParseResponseError> {
54 match &self.inner {
55 Inner::Oauth2V3UserInfoEndpoint(ep) => UserInfo::try_from(ep.parse_response(response)?)
56 .map_err(EndpointParseResponseError::ToOutputFailed),
57 Inner::OidcV1UserInfoEndpoint(ep) => UserInfo::try_from(ep.parse_response(response)?)
58 .map_err(EndpointParseResponseError::ToOutputFailed),
59 }
60 }
61}
62
63impl From<Oauth2V3UserInfoEndpointError> for EndpointRenderRequestError {
65 fn from(err: Oauth2V3UserInfoEndpointError) -> Self {
66 match err {
67 Oauth2V3UserInfoEndpointError::MakeRequestFailed(err) => Self::MakeRequestFailed(err),
68 Oauth2V3UserInfoEndpointError::DeResponseBodyFailed(err) => Self::Other(Box::new(err)),
69 }
70 }
71}
72impl From<Oauth2V3UserInfoEndpointError> for EndpointParseResponseError {
73 fn from(err: Oauth2V3UserInfoEndpointError) -> Self {
74 match err {
75 Oauth2V3UserInfoEndpointError::MakeRequestFailed(err) => Self::Other(Box::new(err)),
76 Oauth2V3UserInfoEndpointError::DeResponseBodyFailed(err) => {
77 Self::DeResponseBodyFailed(err)
78 }
79 }
80 }
81}
82
83impl TryFrom<Oauth2V3UserInfo> for UserInfo {
85 type Error = Box<dyn std::error::Error + Send + Sync>;
86
87 fn try_from(user_info: Oauth2V3UserInfo) -> Result<Self, Self::Error> {
88 Ok(Self {
89 uid: user_info.sub.to_owned(),
90 name: None,
91 email: user_info.email.to_owned(),
92 raw: serde_json::to_value(user_info)
93 .map(|x| x.as_object().cloned())?
94 .ok_or_else(|| "unreachable".to_owned())?,
95 })
96 }
97}
98
99impl From<OidcV1UserInfoEndpointError> for EndpointRenderRequestError {
101 fn from(err: OidcV1UserInfoEndpointError) -> Self {
102 match err {
103 OidcV1UserInfoEndpointError::MakeRequestFailed(err) => Self::MakeRequestFailed(err),
104 OidcV1UserInfoEndpointError::DeResponseBodyFailed(err) => Self::Other(Box::new(err)),
105 }
106 }
107}
108impl From<OidcV1UserInfoEndpointError> for EndpointParseResponseError {
109 fn from(err: OidcV1UserInfoEndpointError) -> Self {
110 match err {
111 OidcV1UserInfoEndpointError::MakeRequestFailed(err) => Self::Other(Box::new(err)),
112 OidcV1UserInfoEndpointError::DeResponseBodyFailed(err) => {
113 Self::DeResponseBodyFailed(err)
114 }
115 }
116 }
117}
118
119impl TryFrom<OidcV1UserInfo> for UserInfo {
121 type Error = Box<dyn std::error::Error + Send + Sync>;
122
123 fn try_from(user_info: OidcV1UserInfo) -> Result<Self, Self::Error> {
124 Ok(Self {
125 uid: user_info.sub.to_owned(),
126 name: user_info.name.to_owned(),
127 email: user_info.email.to_owned(),
128 raw: serde_json::to_value(user_info)
129 .map(|x| x.as_object().cloned())?
130 .ok_or_else(|| "unreachable".to_owned())?,
131 })
132 }
133}