Skip to content

Commit b7df867

Browse files
committed
feat (Login): Add OIDC login support
1 parent f8ea394 commit b7df867

File tree

11 files changed

+179
-22
lines changed

11 files changed

+179
-22
lines changed

Cargo.lock

Lines changed: 35 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ google-login = ["third-party-login"]
1515
github-login = ["third-party-login"]
1616
gitlab-login = ["third-party-login"]
1717
microsoft-login = ["third-party-login"]
18-
all-login = ["google-login", "github-login", "gitlab-login", "microsoft-login"]
18+
oidc-login = ["third-party-login"]
19+
all-login = ["google-login", "github-login", "gitlab-login", "microsoft-login", "oidc-login"]
1920

2021
[dev-dependencies]
2122
dotenvy = "0.15.6"
@@ -38,4 +39,5 @@ serde = { version = "1", features = ["derive"] }
3839
serde_yaml = "0.9.34-deprecated"
3940
uuid = { version = "1", features = ["serde", "v4"] }
4041
tera = { version = "1", optional = true }
41-
reqwest = { version = "0.12.4", features = ["json", "rustls-tls"], default-features = false, optional = true }
42+
reqwest = { version = "0.12.4", features = ["json", "rustls-tls"], default-features = false, optional = true }
43+
tokio = { version = "1.47.1", features = ["sync"] }

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ rtabby-web-api store tabby's configuration in a database. You can choose between
7070
```
7171
Token must be a valid and unique uuid v4. You can create one [here](https://www.uuidgenerator.net/version4).
7272

73-
rTabby supports OAuth2 providers like Github, Gitlab, Google or Microsoft. You can enable them by adding OAuth client and secret through env var in your `docker-compose.yml`.
73+
rTabby supports OAuth2 providers like Github, Gitlab, Google, Microsoft or OpenID Connect (OIDC). You can enable them by adding OAuth client and secret through env var in your `docker-compose.yml`. For OIDC, you'll also need to provide your configuration url (ends with `/.well-known/openid-configuration`).
7474
OAuth login callback is `/login/{provider}/callback`.
7575
7676
```yml
@@ -84,6 +84,9 @@ rtabby-web-api store tabby's configuration in a database. You can choose between
8484
#- GOOGLE_APP_CLIENT_SECRET=
8585
#- MICROSOFT_APP_CLIENT_ID=
8686
#- MICROSOFT_APP_CLIENT_SECRET=
87+
#- OIDC_APP_CLIENT_ID=
88+
#- OIDC_APP_CLIENT_SECRET=
89+
#- OIDC_APP_CONFIG_URL=
8790
```
8891
8992
When using OAuth prividers, browse to `http://<rtabby instance>/login` to authenticate and create your user and token.

docker-compose-sqlite.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ services:
3535
#- GOOGLE_APP_CLIENT_SECRET=
3636
#- MICROSOFT_APP_CLIENT_ID=
3737
#- MICROSOFT_APP_CLIENT_SECRET=
38+
#- OIDC_APP_CLIENT_ID=
39+
#- OIDC_APP_CLIENT_SECRET=
40+
#- OIDC_APP_CONFIG_URL=
3841
volumes:
3942
- ./config:/config
4043
networks:

docker-compose.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ services:
3434
#- GOOGLE_APP_CLIENT_SECRET=
3535
#- MICROSOFT_APP_CLIENT_ID=
3636
#- MICROSOFT_APP_CLIENT_SECRET=
37+
#- OIDC_APP_CLIENT_ID=
38+
#- OIDC_APP_CLIENT_SECRET=
39+
#- OIDC_APP_CONFIG_URL=
3740

3841
volumes:
3942
- ./config:/config

src/login/error.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ impl fmt::Display for ProviderError {
2222
pub enum OauthError {
2323
UserInfo(reqwest::Error),
2424
AccessToken(reqwest::Error),
25+
OIDCConfiguration(reqwest::Error),
2526
}
2627

2728
impl error::Error for OauthError {}
@@ -32,7 +33,8 @@ impl fmt::Display for OauthError {
3233
Self::UserInfo(ref err) => write!(f, "Unable to retreive OAuth user info: {err}"),
3334
Self::AccessToken(ref err) => {
3435
write!(f, "Unable to retreive OAuth user access token: {err}")
35-
}
36+
},
37+
Self::OIDCConfiguration(ref err) => write!(f, "Unable to retreive OIDC configuration: {err}")
3638
}
3739
}
3840
}

src/login/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ use providers::gitlab;
1818
use providers::google;
1919
#[cfg(feature = "microsoft-login")]
2020
use providers::microsoft;
21+
#[cfg(feature = "oidc-login")]
22+
use providers::oidc;
2123

2224
use self::providers::OauthInfo;
2325

@@ -94,6 +96,16 @@ pub fn get_provider_config() -> ProvidersConfig {
9496
}));
9597
}
9698

99+
#[cfg(feature = "oidc-login")]
100+
if app_env::var(oidc::env::ENV_OIDC_APP_CLIENT_ID).is_ok()
101+
&& app_env::var(oidc::env::ENV_OIDC_APP_CLIENT_SECRET).is_ok()
102+
{
103+
available_providers.push(providers::Provider::Oidc(OauthInfo {
104+
client_id: app_env::var(oidc::env::ENV_OIDC_APP_CLIENT_ID).unwrap(),
105+
client_secret: app_env::var(oidc::env::ENV_OIDC_APP_CLIENT_SECRET).unwrap(),
106+
}));
107+
}
108+
97109
ProvidersConfig {
98110
https_callback,
99111
available_providers,

src/login/providers/mod.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ pub mod gitlab;
66
pub mod google;
77
#[cfg(feature = "microsoft-login")]
88
pub mod microsoft;
9+
#[cfg(feature = "oidc-login")]
10+
pub mod oidc;
911

1012
use super::error::OauthError;
1113
use serde::{Deserialize, Serialize};
@@ -22,6 +24,7 @@ pub struct OauthInfo {
2224

2325
#[derive(Debug, Deserialize)]
2426
pub struct OauthUserInfo<I = String, N = String> {
27+
#[serde(rename = "sub")] // "id" is called "sub" in the OIDC speficication
2528
id: I,
2629
name: N,
2730
}
@@ -52,6 +55,8 @@ pub enum Provider {
5255
Google(OauthInfo),
5356
#[cfg(feature = "microsoft-login")]
5457
Microsoft(OauthInfo),
58+
#[cfg(feature = "oidc-login")]
59+
Oidc(OauthInfo),
5560
}
5661

5762
impl Provider {
@@ -69,6 +74,8 @@ impl Provider {
6974
Self::Google(oauth) => oauth.clone(),
7075
#[cfg(feature = "microsoft-login")]
7176
Self::Microsoft(oauth) => oauth.clone(),
77+
#[cfg(feature = "oidc-login")]
78+
Self::Oidc(oauth) => oauth.clone(),
7279
}
7380
}
7481

@@ -108,15 +115,25 @@ impl Provider {
108115
Self::Microsoft(_) => {
109116
params.push(("scope", "https://graph.microsoft.com/User.Read".to_string()));
110117
}
118+
#[cfg(feature = "oidc-login")]
119+
Self::Oidc(_) => {
120+
params.push(("scope", "profile openid".to_string()));
121+
}
111122
#[cfg(feature = "github-login")]
112123
_ => {}
113124
}
114125

115126
params
116127
}
117128

118-
pub fn get_login_url(&self, scheme: Scheme, host: String, state: String) -> String {
129+
pub async fn get_login_url(
130+
&self,
131+
scheme: Scheme,
132+
host: String,
133+
state: String,
134+
) -> Result<String, OauthError> {
119135
let params = self.get_login_url_params(scheme, host, state);
136+
let oidc_config = oidc::get_oidc_config().await?;
120137

121138
let oauth_url = match self {
122139
#[cfg(feature = "github-login")]
@@ -127,11 +144,15 @@ impl Provider {
127144
Self::Google(_) => google::GOOGLE_OAUTH_AUTHORIZE_URL,
128145
#[cfg(feature = "microsoft-login")]
129146
Self::Microsoft(_) => microsoft::MICROSOFT_OAUTH_AUTHORIZE_URL,
147+
#[cfg(feature = "oidc-login")]
148+
Self::Oidc(_) => &oidc_config.authorization_endpoint,
130149
};
131150

132-
reqwest::Url::parse_with_params(oauth_url, params)
151+
let url = reqwest::Url::parse_with_params(oauth_url, params)
133152
.unwrap()
134-
.to_string()
153+
.to_string();
154+
155+
Ok(url.to_string())
135156
}
136157

137158
#[allow(unused_variables)]
@@ -152,6 +173,8 @@ impl Provider {
152173
Self::Microsoft(oauth) => microsoft::user_info(scheme, oauth, host, token)
153174
.await?
154175
.into(),
176+
#[cfg(feature = "oidc-login")]
177+
Self::Oidc(oauth) => oidc::user_info(scheme, oauth, host, token).await?.into(),
155178
};
156179

157180
Ok(ThirdPartyUserInfo {
@@ -182,6 +205,8 @@ impl fmt::Display for Provider {
182205
Self::Google(_) => write!(f, "Google"),
183206
#[cfg(feature = "microsoft-login")]
184207
Self::Microsoft(_) => write!(f, "Microsoft"),
208+
#[cfg(feature = "oidc-login")]
209+
Self::Oidc(_) => write!(f, "OIDC"),
185210
}
186211
}
187212
}

0 commit comments

Comments
 (0)