OIDC example connects, now to fix my kanidm setup
This commit is contained in:
parent
ac4dfca0ac
commit
9d3c7efbba
6 changed files with 51 additions and 116 deletions
77
Cargo.lock
generated
77
Cargo.lock
generated
|
@ -1127,20 +1127,6 @@ dependencies = [
|
|||
"native-tls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-rustls"
|
||||
version = "0.24.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"http 0.2.12",
|
||||
"hyper 0.14.30",
|
||||
"rustls 0.21.12",
|
||||
"tokio",
|
||||
"tokio-rustls 0.24.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-rustls"
|
||||
version = "0.27.2"
|
||||
|
@ -1151,10 +1137,10 @@ dependencies = [
|
|||
"http 1.1.0",
|
||||
"hyper 1.4.1",
|
||||
"hyper-util",
|
||||
"rustls 0.23.12",
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"tokio",
|
||||
"tokio-rustls 0.26.0",
|
||||
"tokio-rustls",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
|
@ -1634,7 +1620,6 @@ dependencies = [
|
|||
"getrandom 0.2.15",
|
||||
"http 0.2.12",
|
||||
"rand 0.8.5",
|
||||
"reqwest 0.11.27",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_path_to_error",
|
||||
|
@ -2202,7 +2187,6 @@ dependencies = [
|
|||
"http 0.2.12",
|
||||
"http-body 0.4.6",
|
||||
"hyper 0.14.30",
|
||||
"hyper-rustls 0.24.2",
|
||||
"hyper-tls 0.5.0",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
|
@ -2213,7 +2197,6 @@ dependencies = [
|
|||
"once_cell",
|
||||
"percent-encoding 2.3.1",
|
||||
"pin-project-lite",
|
||||
"rustls 0.21.12",
|
||||
"rustls-pemfile 1.0.4",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
@ -2222,14 +2205,12 @@ dependencies = [
|
|||
"system-configuration",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tokio-rustls 0.24.1",
|
||||
"tokio-socks",
|
||||
"tower-service",
|
||||
"url 2.5.2",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"webpki-roots",
|
||||
"winreg 0.50.0",
|
||||
]
|
||||
|
||||
|
@ -2249,7 +2230,7 @@ dependencies = [
|
|||
"http-body 1.0.1",
|
||||
"http-body-util",
|
||||
"hyper 1.4.1",
|
||||
"hyper-rustls 0.27.2",
|
||||
"hyper-rustls",
|
||||
"hyper-tls 0.6.0",
|
||||
"hyper-util",
|
||||
"ipnet",
|
||||
|
@ -2496,18 +2477,6 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.21.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e"
|
||||
dependencies = [
|
||||
"log 0.4.22",
|
||||
"ring",
|
||||
"rustls-webpki 0.101.7",
|
||||
"sct",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.12"
|
||||
|
@ -2516,7 +2485,7 @@ checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044"
|
|||
dependencies = [
|
||||
"once_cell",
|
||||
"rustls-pki-types",
|
||||
"rustls-webpki 0.102.6",
|
||||
"rustls-webpki",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
@ -2546,16 +2515,6 @@ version = "1.7.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d"
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.101.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.102.6"
|
||||
|
@ -2609,16 +2568,6 @@ version = "1.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "sct"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sec1"
|
||||
version = "0.7.3"
|
||||
|
@ -3073,23 +3022,13 @@ dependencies = [
|
|||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.24.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
|
||||
dependencies = [
|
||||
"rustls 0.21.12",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
|
||||
dependencies = [
|
||||
"rustls 0.23.12",
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"tokio",
|
||||
]
|
||||
|
@ -3515,12 +3454,6 @@ dependencies = [
|
|||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.25.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
|
||||
|
||||
[[package]]
|
||||
name = "websocket"
|
||||
version = "0.18.0"
|
||||
|
|
|
@ -15,11 +15,12 @@ reqwest-tracing = "0.5.0"
|
|||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
serde_json = "1.0.115"
|
||||
serde_with = "3.7.0"
|
||||
tokio = { workspace = true }
|
||||
tracing = "0.1.40"
|
||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||
urlencoding = "2.1.3"
|
||||
openidconnect = { version = "3.5.0", default_features = false }
|
||||
|
||||
http_client = { workspace = true }
|
||||
discord_bot = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
openidconnect = "3.5.0"
|
||||
tokio = { workspace = true }
|
||||
|
|
|
@ -6,65 +6,58 @@ use color_eyre::{eyre::eyre, Result};
|
|||
use openidconnect::core::{
|
||||
CoreAuthenticationFlow, CoreClient, CoreProviderMetadata, CoreUserInfoClaims,
|
||||
};
|
||||
use openidconnect::AuthorizationCode;
|
||||
use openidconnect::{
|
||||
AccessTokenHash, ClientId, CsrfToken, HttpResponse, IssuerUrl, Nonce, PkceCodeChallenge,
|
||||
RedirectUrl, Scope,
|
||||
};
|
||||
use openidconnect::{AuthorizationCode, PolicyUrl};
|
||||
|
||||
const ISSUER_URL: &str = "https://localhost:8443/oauth2/openid/yourcloud";
|
||||
const CLIENT_ID: &str = "yourcloud";
|
||||
const REDIRECT_URL: &str = "http://localhost:3000/oauth2/handler";
|
||||
const SCOPES: [&str; 3] = ["read", "write", "email"];
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum Error {
|
||||
/// Error returned by reqwest crate.
|
||||
#[error("request failed")]
|
||||
Reqwest(#[source] reqwest::Error),
|
||||
/// I/O error.
|
||||
#[error("I/O error")]
|
||||
Io(#[source] std::io::Error),
|
||||
/// Other error.
|
||||
#[error("Other error: {}", _0)]
|
||||
Other(String),
|
||||
}
|
||||
use http_client::{Client, Error};
|
||||
|
||||
fn http_client(request: openidconnect::HttpRequest) -> Result<HttpResponse, Error> {
|
||||
let client = reqwest::Client::builder()
|
||||
// Following redirects opens the client up to SSRF vulnerabilities.
|
||||
.redirect(Policy::none())
|
||||
.build()
|
||||
.map_err(Error::Reqwest)?;
|
||||
pub async fn async_http_client(request: openidconnect::HttpRequest) -> Result<HttpResponse, Error> {
|
||||
let builder = {
|
||||
let mut builder = Client::builder();
|
||||
builder.client_builder = builder
|
||||
.client_builder
|
||||
.danger_accept_invalid_certs(true) // hitting localhost
|
||||
.redirect(http_client::reqwest::redirect::Policy::none());
|
||||
builder
|
||||
};
|
||||
|
||||
let mut request_builder = client
|
||||
.request(request.method, request.url.as_str())
|
||||
let mut request_builder = builder
|
||||
.build()?
|
||||
.build_request(request.method, request.url.as_str())?
|
||||
.body(request.body);
|
||||
|
||||
for (name, value) in &request.headers {
|
||||
request_builder = request_builder.header(name.as_str(), value.as_bytes());
|
||||
}
|
||||
let mut response = client
|
||||
.execute(request_builder.build().map_err(Error::Reqwest)?)
|
||||
.map_err(Error::Reqwest)?;
|
||||
let response = request_builder.send().await?;
|
||||
|
||||
let mut body = Vec::new();
|
||||
response.read_to_end(&mut body).map_err(Error::Io)?;
|
||||
|
||||
{
|
||||
Ok(HttpResponse {
|
||||
status_code: response.status(),
|
||||
headers: response.headers().to_owned(),
|
||||
body,
|
||||
})
|
||||
}
|
||||
let status_code = response.status();
|
||||
let headers = response.headers().to_owned();
|
||||
let chunks = response.bytes().await.map_err(Error::Reqwest)?;
|
||||
Ok(HttpResponse {
|
||||
status_code,
|
||||
headers,
|
||||
body: chunks.to_vec(),
|
||||
})
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
// Use OpenID Connect Discovery to fetch the provider metadata.
|
||||
use openidconnect::{OAuth2TokenResponse, TokenResponse};
|
||||
let provider_metadata =
|
||||
CoreProviderMetadata::discover(&IssuerUrl::new(ISSUER_URL.to_string())?, http_client)?;
|
||||
let provider_metadata = CoreProviderMetadata::discover_async(
|
||||
IssuerUrl::new(ISSUER_URL.to_string())?,
|
||||
async_http_client,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Create an OpenID Connect client by specifying the client ID, client secret, authorization URL
|
||||
// and token URL.
|
||||
|
@ -114,7 +107,8 @@ fn main() -> Result<()> {
|
|||
.exchange_code(AuthorizationCode::new(authorization_code))
|
||||
// Set the PKCE code verifier.
|
||||
.set_pkce_verifier(pkce_verifier)
|
||||
.request(http_client)?;
|
||||
.request_async(async_http_client)
|
||||
.await?;
|
||||
|
||||
// Extract the ID token claims after verifying its authenticity and nonce.
|
||||
let id_token = token_response
|
||||
|
@ -151,7 +145,8 @@ fn main() -> Result<()> {
|
|||
let userinfo: CoreUserInfoClaims = client
|
||||
.user_info(token_response.access_token().to_owned(), None)
|
||||
.map_err(|err| eyre!("No user info endpoint: {:?}", err))?
|
||||
.request(http_client)
|
||||
.request_async(async_http_client)
|
||||
.await
|
||||
.map_err(|err| eyre!("Failed requesting user info: {:?}", err))?;
|
||||
|
||||
println!("{:#?}", userinfo);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p ripgrep oath-toolkit
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
FAKE_PASSWORD="f0rTkN0x1s_cool"
|
||||
function kdrun {
|
||||
podman exec -it kanidm "$@"
|
||||
|
@ -13,7 +15,7 @@ echo "admin password: $admin_password"
|
|||
echo "idm_admin password: $idm_password"
|
||||
|
||||
# start a kanidm client in the background for an hour
|
||||
podman kill kanidm-client || true
|
||||
podman kill kanidm-client &>/dev/null || true
|
||||
sleep 0.2
|
||||
|
||||
podman run -itd --rm \
|
||||
|
|
|
@ -5,4 +5,4 @@ podman run -itd --rm \
|
|||
-v "$PWD/chain.pem:/data/chain.pem:ro" \
|
||||
-v "$PWD/key.pem:/data/key.pem:ro" \
|
||||
--name kanidm \
|
||||
docker.io/kanidm/server:latest
|
||||
docker.io/kanidm/server:latest &>/dev/null || true
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
pub use reqwest;
|
||||
pub use reqwest::header::{HeaderMap, HeaderValue};
|
||||
pub use reqwest::{Body, ClientBuilder, Method, Response, Url};
|
||||
pub use reqwest_middleware::ClientBuilder as MiddlewareClientBuilder;
|
||||
|
@ -16,6 +17,8 @@ pub struct Client {
|
|||
}
|
||||
|
||||
pub struct Builder {
|
||||
pub client_builder: ClientBuilder,
|
||||
// middleware_client_builder: MiddlewareClientBuilder,
|
||||
middleware: Option<Box<Vec<Arc<dyn Middleware>>>>,
|
||||
default_headers: Option<HeaderMap>,
|
||||
base_url: Option<Url>,
|
||||
|
@ -33,6 +36,7 @@ impl Default for Builder {
|
|||
middleware.push(Arc::new(TracingMiddleware::default()));
|
||||
|
||||
Builder {
|
||||
client_builder: ClientBuilder::new(),
|
||||
name: None,
|
||||
base_url: None,
|
||||
default_headers: None,
|
||||
|
@ -70,7 +74,7 @@ impl Builder {
|
|||
}
|
||||
|
||||
pub fn build(mut self) -> Result<Client> {
|
||||
let mut builder = reqwest::Client::builder();
|
||||
let mut builder = self.client_builder;
|
||||
|
||||
if let Some(headers) = self.default_headers {
|
||||
builder = builder.default_headers(headers);
|
||||
|
|
Loading…
Reference in a new issue