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}