1
0
Fork 0

add oauth2 testing

This commit is contained in:
Cyborus 2024-05-22 19:28:44 -04:00
parent 119571229c
commit 014a90048f
No known key found for this signature in database
3 changed files with 178 additions and 1 deletions

75
Cargo.lock generated
View file

@ -89,6 +89,34 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cookie"
version = "0.16.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb"
dependencies = [
"percent-encoding",
"time",
"version_check",
]
[[package]]
name = "cookie_store"
version = "0.16.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d606d0fba62e13cf04db20536c05cb7f13673c161cb47a47a82b9b9e7d3f1daa"
dependencies = [
"cookie",
"idna 0.2.3",
"log",
"publicsuffix",
"serde",
"serde_derive",
"serde_json",
"time",
"url",
]
[[package]]
name = "core-foundation"
version = "0.9.3"
@ -356,6 +384,27 @@ dependencies = [
"tokio-native-tls",
]
[[package]]
name = "idna"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
dependencies = [
"matches",
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "idna"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
dependencies = [
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "idna"
version = "0.5.0"
@ -427,6 +476,12 @@ version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "matches"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
[[package]]
name = "memchr"
version = "2.6.4"
@ -585,6 +640,22 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "psl-types"
version = "2.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac"
[[package]]
name = "publicsuffix"
version = "2.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96a8c1bda5ae1af7f99a2962e49df150414a43d62404644d98dd5c3a93d07457"
dependencies = [
"idna 0.3.0",
"psl-types",
]
[[package]]
name = "quote"
version = "1.0.35"
@ -611,6 +682,8 @@ checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b"
dependencies = [
"base64",
"bytes",
"cookie",
"cookie_store",
"encoding_rs",
"futures-core",
"futures-util",
@ -1005,7 +1078,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
dependencies = [
"form_urlencoded",
"idna",
"idna 0.5.0",
"percent-encoding",
"serde",
]

View file

@ -24,4 +24,5 @@ zeroize = "1.7.0"
[dev-dependencies]
eyre = "0.6.9"
reqwest = { version = "0.11.18", features = ["cookies"] }
tokio = { version = "1.29.1", features = ["net", "fs", "rt", "macros"] }

View file

@ -430,3 +430,106 @@ async fn admin() {
.await
.expect("failed to delete hook");
}
#[tokio::test]
async fn oauth2_login() {
let api = get_api();
let opt = forgejo_api::structs::CreateOAuth2ApplicationOptions {
confidential_client: Some(true),
name: Some("Test Application".into()),
redirect_uris: Some(vec!["http://127.0.0.1:48879/".into()]),
};
let app = api.user_create_oauth2_application(opt).await.unwrap();
let client_id = app.client_id.unwrap();
let client_secret = app.client_secret.unwrap();
let base_url = &std::env::var("FORGEJO_API_CI_INSTANCE_URL").unwrap();
let client = reqwest::Client::builder()
.cookie_store(true)
.redirect(reqwest::redirect::Policy::none())
.build()
.unwrap();
// Log in via the web interface
let _ = client
.post(&format!("{base_url}user/login"))
.form(&[("user_name", "TestingAdmin"), ("password", "password")])
.send()
.await
.unwrap()
.error_for_status()
.unwrap();
// Load the authorization page
let response = client
.get(&format!(
"{base_url}login/oauth/authorize\
?client_id={client_id}\
&redirect_uri=http%3A%2F%2F127.0.0.1%3A48879%2F\
&response_type=code\
&state=theyve"
))
.send()
.await
.unwrap()
.error_for_status()
.unwrap();
let csrf = response.cookies().find(|x| x.name() == "_csrf").unwrap();
// Authorize the new application via the web interface
let response = client
.post(&format!("{base_url}login/oauth/grant"))
.form(&[
("_csrf", csrf.value()),
("client_id", &client_id),
("state", "theyve"),
("scope", ""),
("nonce", ""),
("redirect_uri", "http://127.0.0.1:48879/"),
])
.send()
.await
.unwrap()
.error_for_status()
.unwrap();
// Extract the code from the redirect url
let location = response.headers().get(reqwest::header::LOCATION).unwrap();
let location = url::Url::parse(dbg!(location.to_str().unwrap())).unwrap();
let mut code = None;
for (key, value) in location.query_pairs() {
if key == "code" {
code = Some(value.into_owned());
} else if key == "error_description" {
panic!("{value}");
}
}
let code = code.unwrap();
// Redeem the code and check it works
let url = url::Url::parse(&base_url).unwrap();
let api = Forgejo::new(forgejo_api::Auth::None, url.clone()).unwrap();
let request = forgejo_api::structs::OAuthTokenRequest::Confidential {
client_id: &client_id,
client_secret: &client_secret,
code: &code,
redirect_uri: url::Url::parse("http://127.0.0.1:48879/").unwrap(),
};
let token = api.oauth_get_access_token(request).await.unwrap();
let token_api =
Forgejo::new(forgejo_api::Auth::OAuth2(&token.access_token), url.clone()).unwrap();
let myself = token_api.user_get_current().await.unwrap();
assert_eq!(myself.login.as_deref(), Some("TestingAdmin"));
let request = forgejo_api::structs::OAuthTokenRequest::Refresh {
refresh_token: &token.refresh_token,
client_id: &client_id,
client_secret: &client_secret,
};
let token = token_api.oauth_get_access_token(request).await.unwrap();
let token_api = Forgejo::new(forgejo_api::Auth::OAuth2(&token.access_token), url).unwrap();
let myself = token_api.user_get_current().await.unwrap();
assert_eq!(myself.login.as_deref(), Some("TestingAdmin"));
}