File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -631,12 +631,23 @@ pub struct Options {
631631 long = "oidc-scope" ,
632632 name = "oidc-scope" ,
633633 env = "P_OIDC_SCOPE" ,
634- default_value = "openid profile email offline_access " ,
634+ default_value = "openid profile email" ,
635635 required = false ,
636- help = "OIDC scope to request (default: openid profile email offline_access )"
636+ help = "OIDC scope to request (default: openid profile email)"
637637 ) ]
638638 pub scope : String ,
639639
640+ // additional query params for oidc auth url
641+ #[ arg(
642+ long,
643+ name = "oidc-query-params" ,
644+ env = "P_OIDC_QUERY_PARAMS" ,
645+ value_parser = validation:: validate_query_params,
646+ required = false ,
647+ help = "Additional query params to add to the auth url"
648+ ) ]
649+ pub oidc_query_params : Option < String > ,
650+
640651 // event's maximum chunk age in hours
641652 #[ arg(
642653 long,
Original file line number Diff line number Diff line change @@ -96,7 +96,13 @@ pub async fn login(
9696 let scope = PARSEABLE . options . scope . to_string ( ) ;
9797 let mut auth_url: String = client. read ( ) . await . auth_url ( & scope, Some ( redirect) ) . into ( ) ;
9898
99- auth_url. push_str ( "&access_type=offline" ) ;
99+ if let Some ( query_params) = PARSEABLE . options . oidc_query_params . as_ref ( ) {
100+ if !query_params. starts_with ( '&' ) {
101+ auth_url = format ! ( "{auth_url}&{query_params}" ) ;
102+ } else {
103+ auth_url. push_str ( query_params. as_str ( ) ) ;
104+ }
105+ }
100106 return Ok ( HttpResponse :: TemporaryRedirect ( )
101107 . insert_header ( ( actix_web:: http:: header:: LOCATION , auth_url) )
102108 . finish ( ) ) ;
@@ -153,7 +159,13 @@ pub async fn login(
153159 . await
154160 . auth_url ( & scope, Some ( redirect) )
155161 . into ( ) ;
156- auth_url. push_str ( "&access_type=offline" ) ;
162+ if let Some ( query_params) = PARSEABLE . options . oidc_query_params . as_ref ( ) {
163+ if !query_params. starts_with ( '&' ) {
164+ auth_url = format ! ( "{auth_url}&{query_params}" ) ;
165+ } else {
166+ auth_url. push_str ( query_params. as_str ( ) ) ;
167+ }
168+ }
157169 HttpResponse :: TemporaryRedirect ( )
158170 . insert_header ( ( actix_web:: http:: header:: LOCATION , auth_url) )
159171 . finish ( )
Original file line number Diff line number Diff line change @@ -209,6 +209,56 @@ pub mod validation {
209209 }
210210 }
211211
212+ pub fn validate_query_params ( mut query : & str ) -> Result < String , String > {
213+ fn valid_component ( value : & str ) -> bool {
214+ let bytes = value. as_bytes ( ) ;
215+ let mut i = 0 ;
216+
217+ while i < bytes. len ( ) {
218+ match bytes[ i] {
219+ b'%' if i + 2 < bytes. len ( )
220+ && bytes[ i + 1 ] . is_ascii_hexdigit ( )
221+ && bytes[ i + 2 ] . is_ascii_hexdigit ( ) =>
222+ {
223+ i += 3 ;
224+ }
225+ b if b. is_ascii_alphanumeric ( )
226+ || matches ! ( b, b'-' | b'.' | b'_' | b'~' | b'+' ) =>
227+ {
228+ i += 1 ;
229+ }
230+ _ => return false ,
231+ }
232+ }
233+
234+ true
235+ }
236+
237+ if query. is_empty ( ) {
238+ return Err ( "query string cannot be empty" . into ( ) ) ;
239+ }
240+ query = if let Some ( query) = query. strip_prefix ( '&' ) {
241+ query
242+ } else {
243+ query
244+ } ;
245+ for param in query. split ( '&' ) {
246+ let ( key, value) = param
247+ . split_once ( '=' )
248+ . ok_or_else ( || format ! ( "invalid parameter: {param}" ) ) ?;
249+
250+ if key. is_empty ( ) {
251+ return Err ( "parameter key cannot be empty" . into ( ) ) ;
252+ }
253+
254+ if !valid_component ( key) || !valid_component ( value) {
255+ return Err ( format ! ( "invalid characters in parameter: {param}" ) ) ;
256+ }
257+ }
258+
259+ Ok ( query. to_owned ( ) )
260+ }
261+
212262 pub fn validate_payload_size ( s : & str ) -> Result < usize , String > {
213263 const MIN_SIZE : usize = 100 ; // 100 bytes
214264 const MAX_SIZE : usize = 100 * 1024 * 1024 ; // 100 MB
You can’t perform that action at this time.
0 commit comments