add oauth2 testing
This commit is contained in:
		
							parent
							
								
									119571229c
								
							
						
					
					
						commit
						014a90048f
					
				
					 3 changed files with 178 additions and 1 deletions
				
			
		
							
								
								
									
										75
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										75
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							| 
						 | 
				
			
			@ -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",
 | 
			
		||||
]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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"] }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										103
									
								
								tests/ci_test.rs
									
										
									
									
									
								
							
							
						
						
									
										103
									
								
								tests/ci_test.rs
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -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"));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue