Skip to main content

unilim_cas/
lib.rs

1//! authentication client for the central authentication service of
2//! [unilim](https://www.unilim.fr), the university of limoges.
3//!
4//! talks to the lemonldap::ng portal at `cas.unilim.fr` and covers the whole
5//! session lifecycle:
6//!
7//! - [`CAS::initialize`] submits credentials and returns a [`PendingAuth`]
8//!   holding the 2fa challenge.
9//! - [`PendingAuth`] solves the challenge with an email code or a totp code,
10//!   then [`PendingAuth::finish`] establishes the session.
11//! - [`CAS::restore`] brings back a persisted session without solving 2fa
12//!   again.
13//! - [`CAS::service`] returns a ticket url for one of the supported
14//!   [`Services`].
15//! - [`CAS::authorize`], [`CAS::tokenize`] and [`CAS::userinfo`] handle the
16//!   oauth2 flow of the portal.
17//!
18//! # quick start
19//!
20//! ```no_run
21//! use unilim_cas::CAS;
22//!
23//! # async fn quick_start() -> unilim_cas::Result<()> {
24//! // on first login, solve the 2fa challenge manually.
25//! let mut auth = CAS::initialize("username", "password").await?;
26//!
27//! if !auth.solved {
28//!     if auth.is_totp_available {
29//!         auth.solve_with_totp("123456").await?;
30//!     }
31//!     else if auth.is_email_available {
32//!         auth.send_email_code().await?;
33//!         auth.solve_with_email_code("123456").await?;
34//!     }
35//! }
36//!
37//! let cas = auth.finish().await?;
38//!
39//! // store `cas.connection` and `cas.key` somewhere safe, then restore
40//! // later without any 2fa prompt.
41//! let cas = CAS::restore("username", "password", &cas.connection, &cas.key).await?;
42//! # Ok(())
43//! # }
44//! ```
45//!
46//! # session model
47//!
48//! an established [`CAS`] session is made of three strings:
49//!
50//! - [`CAS::cookie`], the `lemonldap` session cookie sent on every request.
51//! - [`CAS::connection`], the `llngconnection` persistence cookie obtained
52//!   by registering the browser.
53//! - [`CAS::key`], the totp secret answering the browser check during
54//!   [`CAS::restore`].
55//!
56//! the session cookie expires quickly, so store the other two for the long
57//! term.
58//!
59//! # features
60//!
61//! - `client`, the default, provides the native client documented here. http
62//!   goes through [rikka](https://docs.rs/rikka), so it also runs on
63//!   `wasm32`.
64//! - `wasm` only provides the `unilim_cas::wasm` module, extern declarations
65//!   of the `@unilim/cas` js classes for packages receiving the session from
66//!   javascript. pulls no client code and only compiles on `wasm32`.
67
68#[cfg(feature = "client")]
69mod native;
70#[cfg(feature = "client")]
71pub use native::*;
72
73#[cfg(all(target_arch = "wasm32", feature = "npm"))]
74mod npm;
75
76#[cfg(all(target_arch = "wasm32", feature = "wasm"))]
77pub mod wasm;