1 unstable release
new 0.1.11 | Jan 31, 2025 |
---|
#381 in Authentication
42KB
1K
SLoC
ONES OIDC Rust Authentication Library
Package to authenticate with ONES using OpenID Connect (OIDC) and Client Initiated Backchannel Authentication (CIBA).
Usage
1.0 Device Authentication
use ones_oidc_rust::{OpenIdconnectClient, load_device_config};
let device_config = load_device_config(&device_config_path).expect("Failed to load device config");
let client_id = ClientId::new(device_config.client_id.clone().to_string());
let issuer_url = IssuerUrl::new(device_config.issuer_url.to_string())
.map_err(|_| std::io::Error::new(std::io::ErrorKind::Other, "Failed to parse issuer URL"))?;
let provider_metadata = CoreProviderMetadata::discover_async(
issuer_url.clone(),
async_http_client,
)
.await
.map_err(|_| std::io::Error::new(std::io::ErrorKind::Other, "Failed to discover OIDC metadata"))?;
let openid_client = OpenIdconnectClient {
client_id: client_id,
issuer_url: issuer_url,
issuer_jwks: None,
provider_metadata: provider_metadata.clone(),
// read_private_key: you can supply your own implementation here
private_key: read_private_key(&device_config.private_key_path).unwrap(),
};
1.1 Get Device Access Token
// Reuse the `openid_client` from the previous example
let openid_client = OpenIdconnectClient { ... };
let device_access_token = openid_client.request_device_access_token().await;
2.0 CIBA
Authenticate with user username (OnesID).
2.1 Make CIBA Request
// Reuse the `openid_client` from the previous example
let openid_client = OpenIdconnectClient { ... };
let login_hint = LoginHint {
kind: payload.login_hint_kind,
value: payload.user_identifier.clone(),
};
let result = openid_client.make_ciba_request(
&login_hint,
"openid offline_access profile".to_string(),
"Authorize login to Example.com?".to_string(),
Some("https://example.com".to_string())
).await;
if result.is_err() {
let e = result.err().unwrap();
debug!("Error: {}", e);
return Ok(HttpResponse::InternalServerError().finish());
}
let result = result.unwrap();
Ok(HttpResponse::Ok().json(result))
2.2 Check CIBA Status
// Reuse the `openid_client` from the previous example
let openid_client = OpenIdconnectClient { ... };
let ciba_status = openid_client.check_ciba_status(&auth_request_id).await;
if ciba_status.is_err() {
let ciba_status = ciba_status.unwrap_err();
if ciba_status.to_string() == "Authorization pending" {
println!("Authorization pending");
Ok(HttpResponse::BadRequest().json(ciba_status.to_string()))
} else {
println!("Error: {:?}", ciba_status);
Ok(HttpResponse::InternalServerError().json(ciba_status.to_string()))
}
} else {
let ciba_status = ciba_status.unwrap();
println!("CIBA Status: {:?}", ciba_status);
Ok(HttpResponse::Ok().json(ciba_status))
}
Validate token:
// Reuse the `openid_client` from the previous example
let openid_client = OpenIdconnectClient { ... };
openid_client.validate_token(&id_token).await;
Guix
guix shell rust-cargo rust gcc-toolchain pkg-config openssl
export OPENSSL_DIR=$(dirname $(dirname $(realpath $(which openssl))))
CC=gcc cargo build
Dependencies
~19–34MB
~558K SLoC