Skip to main content

simple_oauth/common/
github.rs

1use serde::Deserialize;
2
3use crate::{
4    SimpleOAuthProvider, UserInfoProvider,
5    types::{OAuthCredentials, UserInfo},
6};
7
8#[derive(Debug, Clone)]
9pub struct GitHub;
10
11/// User info returned from GitHub API
12#[derive(Debug, Deserialize)]
13struct GitHubUserInfo {
14    id: u64,
15    login: String,
16    name: Option<String>,
17    email: Option<String>,
18    avatar_url: Option<String>,
19}
20
21impl SimpleOAuthProvider for GitHub {
22    fn authorize_url(&self) -> &str {
23        "https://github.com/login/oauth/authorize"
24    }
25
26    fn token_url(&self) -> &str {
27        "https://github.com/login/oauth/access_token"
28    }
29
30    fn default_scopes(&self) -> &'static [&'static str] {
31        &["read:user"]
32    }
33}
34
35impl UserInfoProvider for GitHub {
36    fn user_info_url(&self) -> &str {
37        "https://api.github.com/user"
38    }
39
40    fn user_info_headers(&self, _credentials: &OAuthCredentials) -> Vec<(String, String)> {
41        vec![
42            ("Accept".into(), "application/vnd.github+json".into()),
43            ("User-Agent".into(), "fa-sharp/simple-oauth".into()),
44        ]
45    }
46
47    fn extract_user_info(
48        &self,
49        user_info: serde_json::Value,
50    ) -> Result<UserInfo, serde_json::Error> {
51        let info: GitHubUserInfo = serde_json::from_value(user_info)?;
52
53        Ok(UserInfo {
54            id: info.id.to_string(),
55            name: info.name,
56            username: Some(info.login),
57            email: info.email,
58            email_verified: None,
59            avatar_url: info.avatar_url,
60            ..Default::default()
61        })
62    }
63}