synd_auth/device_flow/provider/
github.rs1use std::borrow::Cow;
2
3use reqwest::Url;
4
5use crate::{
6 config,
7 device_flow::{DeviceAccessTokenRequest, DeviceAuthorizationRequest, Provider},
8};
9
10#[derive(Clone)]
11pub struct Github {
12 client_id: Cow<'static, str>,
13 device_authorization_endpoint: Url,
14 token_endpoint: Url,
15}
16
17impl Default for Github {
18 fn default() -> Self {
19 Self::new(config::github::CLIENT_ID)
20 }
21}
22
23impl Github {
24 const DEVICE_AUTHORIZATION_ENDPOINT: &'static str = "https://github.com/login/device/code";
25 const TOKEN_ENDPOINT: &'static str = "https://github.com/login/oauth/access_token";
26 const SCOPE: &'static str = "user:email";
28
29 pub fn new(client_id: impl Into<Cow<'static, str>>) -> Self {
30 Self {
31 client_id: client_id.into(),
32 device_authorization_endpoint: Url::parse(Self::DEVICE_AUTHORIZATION_ENDPOINT).unwrap(),
33 token_endpoint: Url::parse(Self::TOKEN_ENDPOINT).unwrap(),
34 }
35 }
36
37 #[must_use]
38 pub fn with_device_authorization_endpoint(self, endpoint: Url) -> Self {
39 Self {
40 device_authorization_endpoint: endpoint,
41 ..self
42 }
43 }
44
45 #[must_use]
46 pub fn with_token_endpoint(self, endpoint: Url) -> Self {
47 Self {
48 token_endpoint: endpoint,
49 ..self
50 }
51 }
52}
53
54impl Provider for Github {
55 type DeviceAccessTokenRequest<'d> = DeviceAccessTokenRequest<'d>;
56 fn device_authorization_endpoint(&self) -> Url {
57 self.device_authorization_endpoint.clone()
58 }
59
60 fn token_endpoint(&self) -> reqwest::Url {
61 self.token_endpoint.clone()
62 }
63
64 fn device_authorization_request(&self) -> DeviceAuthorizationRequest {
65 DeviceAuthorizationRequest {
66 client_id: self.client_id.clone(),
67 scope: Self::SCOPE.into(),
68 }
69 }
70
71 fn device_access_token_request<'d, 'p: 'd>(
72 &'p self,
73 device_code: &'d str,
74 ) -> DeviceAccessTokenRequest<'d> {
75 DeviceAccessTokenRequest::new(device_code, self.client_id.as_ref())
76 }
77}