# 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
```rs
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
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
```rs
// 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
```rs
// 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
```rs
// 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:
```rs
// Reuse the `openid_client` from the previous example
let openid_client = OpenIdconnectClient { ... };
openid_client.validate_token(&id_token).await;
```
## Guix
```bash
guix shell rust-cargo rust gcc-toolchain pkg-config openssl
export OPENSSL_DIR=$(dirname $(dirname $(realpath $(which openssl))))
CC=gcc cargo build
```