casdoor_rust_sdk/service/
auth.rs

1// Copyright 2022 The Casdoor Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::entity::{CasdoorConfig, CasdoorUser};
16
17use jsonwebtoken::{Algorithm, DecodingKey, Validation};
18use oauth2::basic::BasicClient;
19use oauth2::reqwest::http_client;
20use oauth2::{AuthUrl, AuthorizationCode, ClientId, ClientSecret, TokenResponse, TokenUrl};
21
22pub struct AuthService<'a> {
23    config: &'a CasdoorConfig,
24}
25
26#[allow(dead_code)]
27impl<'a> AuthService<'a> {
28    pub fn new(config: &'a CasdoorConfig) -> Self {
29        Self { config }
30    }
31
32    pub fn get_auth_token(&self, code: String) -> Result<String, Box<dyn std::error::Error>> {
33        let client_id = ClientId::new(self.config.client_id.clone());
34        let client_secret = ClientSecret::new(self.config.client_secret.clone());
35        let auth_url = AuthUrl::new(format!(
36            "{}/api/login/oauth/authorize",
37            self.config.endpoint
38        ))?;
39        let token_url = TokenUrl::new(format!(
40            "{}/api/login/oauth/access_token",
41            self.config.endpoint
42        ))?;
43        let code = AuthorizationCode::new(code);
44
45        let client = BasicClient::new(client_id, Some(client_secret), auth_url, Some(token_url));
46        let token_res = client.exchange_code(code).request(http_client)?;
47
48        Ok(token_res.access_token().secret().to_string())
49    }
50
51    pub fn parse_jwt_token(
52        &self,
53        token: String,
54    ) -> Result<CasdoorUser, Box<dyn std::error::Error>> {
55        let res = jsonwebtoken::decode::<CasdoorUser>(
56            &token,
57            &DecodingKey::from_rsa_pem(self.config.certificate.as_bytes())?,
58            &Validation::new(Algorithm::RS256),
59        )?;
60
61        Ok(res.claims)
62    }
63
64    pub fn get_signin_url(&self, redirect_url: String) -> String {
65        let scope = "read";
66        let state = self.config.app_name.clone().unwrap_or_default();
67        format!("{}/login/oauth/authorize?client_id={}&response_type=code&redirect_uri={}&scope={}&state={}", 
68            self.config.endpoint,
69            self.config.client_id,
70            urlencoding::encode(&redirect_url).into_owned(),
71            scope, state)
72    }
73
74    pub fn get_signup_url(&self, redirect_url: String) -> String {
75        redirect_url.replace("/login/oauth/authorize", "/signup/oauth/authorize")
76    }
77
78    pub fn get_signup_url_enable_password(&self) -> String {
79        format!(
80            "{}/signup/{}",
81            self.config.endpoint,
82            self.config.app_name.clone().unwrap_or_default()
83        )
84    }
85
86    pub fn get_user_profile_url(&self, uname: String, token: Option<String>) -> String {
87        let param = match token {
88            Some(token) if !token.is_empty() => format!("?access_token={}", token),
89            _ => "".to_string(),
90        };
91        format!(
92            "{}/users/{}/{}{}",
93            self.config.endpoint, self.config.org_name, uname, param
94        )
95    }
96
97    pub fn get_my_profile_url(&self, token: Option<String>) -> String {
98        let param = match token {
99            Some(token) if !token.is_empty() => format!("?access_token={}", token),
100            _ => "".to_string(),
101        };
102        format!("{}/account{}", self.config.endpoint, param)
103    }
104}