oauth2_wechat/extensions/
builder.rs

1use oauth2_client::{
2    extensions::{
3        AccessTokenResponseSuccessfulBody, Builder, BuilderObtainUserInfoError,
4        BuilderObtainUserInfoOutput, GrantInfo, UserInfo,
5    },
6    oauth2_core::types::ScopeParameter,
7    re_exports::Scope,
8};
9
10use crate::{authorization_code_grant::KEY_OPENID, WechatScope};
11
12use super::WechatUserInfoEndpoint;
13
14//
15#[derive(Debug, Clone)]
16pub struct WechatExtensionsBuilder;
17
18impl<SCOPE> Builder<SCOPE> for WechatExtensionsBuilder
19where
20    SCOPE: Scope,
21{
22    fn obtain_user_info(
23        &self,
24        grant_info: GrantInfo<SCOPE>,
25        access_token: &AccessTokenResponseSuccessfulBody<SCOPE>,
26    ) -> Result<BuilderObtainUserInfoOutput, BuilderObtainUserInfoError> {
27        let has_snsapi_login_scope = access_token.scope.as_ref().map(|x| {
28            ScopeParameter::<String>::from(x)
29                .0
30                .contains(&WechatScope::SnsapiLogin.to_string())
31        }) == Some(true);
32
33        if has_snsapi_login_scope {
34            let openid = access_token
35                .extra()
36                .ok_or("extra missing")
37                .map_err(BuilderObtainUserInfoError::Unreachable)?
38                .get(KEY_OPENID)
39                .ok_or("openid missing")
40                .map_err(BuilderObtainUserInfoError::Unreachable)?
41                .as_str()
42                .ok_or("openid mismatch")
43                .map_err(BuilderObtainUserInfoError::Unreachable)?
44                .to_owned();
45
46            return Ok(BuilderObtainUserInfoOutput::Respond(Box::new(
47                WechatUserInfoEndpoint::new(&access_token.access_token, openid),
48            )));
49        }
50
51        match grant_info {
52            GrantInfo::AuthorizationCodeGrant(_) => {
53                let uid = access_token
54                    .extra()
55                    .ok_or("extra missing")
56                    .map_err(BuilderObtainUserInfoError::Unreachable)?
57                    .get(KEY_OPENID)
58                    .ok_or("openid missing")
59                    .map_err(BuilderObtainUserInfoError::Unreachable)?
60                    .as_str()
61                    .ok_or("openid mismatch")
62                    .map_err(BuilderObtainUserInfoError::Unreachable)?
63                    .to_owned();
64
65                return Ok(BuilderObtainUserInfoOutput::Static(UserInfo {
66                    uid,
67                    name: None,
68                    email: None,
69                    raw: Default::default(),
70                }));
71            }
72            GrantInfo::DeviceAuthorizationGrant(_) => {
73                // unknown
74            }
75        }
76
77        Ok(BuilderObtainUserInfoOutput::None)
78    }
79}