sso_ui_jwt/ticket/
handler.rs

1//! Ticket validation handlers.
2
3use http_req::{
4    request::{Method, Request},
5    uri::Uri,
6};
7use strong_xml::XmlRead;
8
9use crate::SSOJWTConfig;
10
11use super::{ServiceResponse, ValidateTicketError};
12
13/// Validates a ticket returned from the CAS SSO server.
14///
15/// # Errors
16///
17/// - [`AuthenticationFailed`][validate_ticket_error]: Failed ticket authentication
18/// - [`RequestError`][validate_ticket_error]: Validation request caused an error
19/// - [`XMLParsingError`][validate_ticket_error]: Error parsing XML response
20///
21/// [validate_ticket_error]: crate::ticket::error::ValidateTicketError
22///
23/// # Examples
24///
25/// ```rust
26/// use sso_ui_jwt::{
27///     ticket::{validate_ticket, ValidateTicketError},
28///     SSOJWTConfig,
29/// };
30///
31/// let config = SSOJWTConfig::new(
32///     120,
33///     120,
34///     String::from("access secret"),
35///     String::from("refresh secret"),
36///     String::from("http://some-service/login"),
37///     String::from("http://some-service"),
38/// );
39///
40/// let response = validate_ticket(&config, "a ticket");
41/// let status = if let Err(ValidateTicketError::XMLParsingError) = response {
42///     "failed"
43/// } else {
44///     "success"
45/// };
46///
47/// assert_eq!(status, "failed");
48/// ```
49pub fn validate_ticket(
50    config: &SSOJWTConfig,
51    ticket: &str,
52) -> Result<ServiceResponse, ValidateTicketError> {
53    let mut writer = Vec::new();
54    let url = format!(
55        "{}/serviceValidate?ticket={}&service={}",
56        config.cas_url, ticket, config.service_url
57    );
58    let uri = Uri::try_from(url.as_str()).unwrap();
59    let mut request = Request::new(&uri);
60
61    let request = request
62        .method(Method::GET)
63        .header("Host", "sso.ui.ac.id")
64        .header("User-Agent", "Node-Fetch");
65
66    match request.send(&mut writer) {
67        Ok(res) => res,
68        Err(_err) => {
69            #[cfg(feature = "log")]
70            log::error!("{}", _err);
71
72            return Err(ValidateTicketError::RequestError);
73        }
74    };
75
76    let content = String::from_utf8_lossy(&writer);
77
78    let response = match ServiceResponse::from_str(&content) {
79        Ok(response) => response,
80        Err(_err) => {
81            #[cfg(feature = "log")]
82            log::error!("{}", _err);
83
84            return Err(ValidateTicketError::XMLParsingError);
85        }
86    };
87
88    match response.authentication_success {
89        Some(_) => Ok(response),
90        None => Err(ValidateTicketError::AuthenticationFailed),
91    }
92}