@@ -37,14 +37,8 @@ use uuid::Uuid;
3737// _authentication_ information. Similarly, the "Unauthorized" HTTP response
3838// code usually describes an _authentication_ error.)
3939//
40- // The above example treats the specified user as a silo user. It's also
41- // possible to use this mechanism to specify a built-in user. In that case, the
42- // bearer token format looks like this:
43- //
44- // Authorization: Bearer oxide-spoof-builtin-<uuid>
45- //
46- // Either way, this mechanism trusts (without verification) that the client is
47- // whoever they say they are. That's true of any bearer token, but this one is
40+ // This mechanism trusts (without verification) that the client is whoever
41+ // they say they are. That's true of any bearer token, but this one is
4842// particularly dangerous because the tokens are long-lived and not secret.
4943
5044pub const SPOOF_SCHEME_NAME : authn:: SchemeName = authn:: SchemeName ( "spoof" ) ;
@@ -63,16 +57,13 @@ lazy_static! {
6357 /// Actor (id) used for the special "bad credentials" error
6458 static ref SPOOF_RESERVED_BAD_CREDS_ACTOR : Actor = Actor :: UserBuiltin {
6559 user_builtin_id: "22222222-2222-2222-2222-222222222222" . parse( ) . unwrap( ) ,
66- silo_id: * crate :: db:: fixed_data:: silo:: SILO_ID ,
6760 } ;
6861 /// Complete HTTP header value to trigger the "bad actor" error
6962 pub static ref SPOOF_HEADER_BAD_ACTOR : Authorization <Bearer > =
70- make_header_value_str( ActorType :: Builtin , SPOOF_RESERVED_BAD_ACTOR )
71- . unwrap( ) ;
63+ make_header_value_str( SPOOF_RESERVED_BAD_ACTOR ) . unwrap( ) ;
7264 /// Complete HTTP header value to trigger the "bad creds" error
7365 pub static ref SPOOF_HEADER_BAD_CREDS : Authorization <Bearer > =
74- make_header_value_str( ActorType :: Builtin , SPOOF_RESERVED_BAD_CREDS )
75- . unwrap( ) ;
66+ make_header_value_str( SPOOF_RESERVED_BAD_CREDS ) . unwrap( ) ;
7667}
7768
7869/// Implements a (test-only) authentication scheme where the client simply
@@ -102,36 +93,19 @@ where
10293 }
10394}
10495
105- /// Specifies whether the spoof header explicitly specifies a built-in user or a
106- /// normal (silo) user
107- #[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
108- pub enum ActorType {
109- Builtin ,
110- Silo ,
111- }
112-
11396fn authn_spoof ( raw_value : Option < & Authorization < Bearer > > ) -> SchemeResult {
11497 let token = match raw_value {
11598 None => return SchemeResult :: NotRequested ,
11699 Some ( bearer) => bearer. token ( ) ,
117100 } ;
118101
119- let str_value = match token. strip_prefix ( SPOOF_PREFIX ) {
120- None => {
121- // This is some other kind of bearer token. Maybe another scheme
122- // knows how to deal with it.
123- return SchemeResult :: NotRequested ;
124- }
125- Some ( s) => s,
126- } ;
127-
128- let ( actor_kind, str_value) = {
129- match str_value. strip_prefix ( "builtin-" ) {
130- Some ( s) => ( ActorType :: Builtin , s) ,
131- None => ( ActorType :: Silo , str_value) ,
132- }
133- } ;
102+ if !token. starts_with ( SPOOF_PREFIX ) {
103+ // This is some other kind of bearer token. Maybe another scheme knows
104+ // how to deal with it.
105+ return SchemeResult :: NotRequested ;
106+ }
134107
108+ let str_value = & token[ SPOOF_PREFIX . len ( ) ..] ;
135109 if str_value == SPOOF_RESERVED_BAD_ACTOR {
136110 return SchemeResult :: Failed ( Reason :: UnknownActor {
137111 actor : str_value. to_owned ( ) ,
@@ -146,16 +120,10 @@ fn authn_spoof(raw_value: Option<&Authorization<Bearer>>) -> SchemeResult {
146120 }
147121
148122 match Uuid :: parse_str ( str_value) . context ( "parsing header value as UUID" ) {
149- Ok ( actor_id) => {
123+ Ok ( silo_user_id) => {
124+ // TODO This should really look up the silo for the given Silo User.
150125 let silo_id = * crate :: db:: fixed_data:: silo:: SILO_ID ;
151- let actor = match actor_kind {
152- ActorType :: Builtin => {
153- Actor :: UserBuiltin { user_builtin_id : actor_id, silo_id }
154- }
155- ActorType :: Silo => {
156- Actor :: SiloUser { silo_user_id : actor_id, silo_id }
157- }
158- } ;
126+ let actor = Actor :: SiloUser { silo_id, silo_user_id } ;
159127 SchemeResult :: Authenticated ( Details { actor } )
160128 }
161129 Err ( source) => SchemeResult :: Failed ( Reason :: BadFormat { source } ) ,
@@ -164,8 +132,8 @@ fn authn_spoof(raw_value: Option<&Authorization<Bearer>>) -> SchemeResult {
164132
165133/// Returns a value of the `Authorization` header for this actor that will be
166134/// accepted using this scheme
167- pub fn make_header_value ( kind : ActorType , id : Uuid ) -> Authorization < Bearer > {
168- make_header_value_str ( kind , & id. to_string ( ) ) . unwrap ( )
135+ pub fn make_header_value ( id : Uuid ) -> Authorization < Bearer > {
136+ make_header_value_str ( & id. to_string ( ) ) . unwrap ( )
169137}
170138
171139/// Returns a value of the `Authorization` header with `str` in the place where
@@ -176,14 +144,9 @@ pub fn make_header_value(kind: ActorType, id: Uuid) -> Authorization<Bearer> {
176144/// this returns a typed value and so cannot be used to make various kinds of
177145/// invalid headers.
178146fn make_header_value_str (
179- kind : ActorType ,
180147 s : & str ,
181148) -> Result < Authorization < Bearer > , anyhow:: Error > {
182- let suffix = match kind {
183- ActorType :: Builtin => format ! ( "builtin-{}" , s) ,
184- ActorType :: Silo => String :: from ( s) ,
185- } ;
186- Authorization :: bearer ( & format ! ( "{}{}" , SPOOF_PREFIX , suffix) )
149+ Authorization :: bearer ( & format ! ( "{}{}" , SPOOF_PREFIX , s) )
187150 . context ( "not a valid HTTP header value" )
188151}
189152
@@ -209,8 +172,6 @@ mod test {
209172 use super :: make_header_value;
210173 use super :: make_header_value_raw;
211174 use super :: make_header_value_str;
212- use super :: ActorType ;
213- use crate :: db;
214175 use headers:: authorization:: Bearer ;
215176 use headers:: authorization:: Credentials ;
216177 use headers:: Authorization ;
@@ -221,18 +182,12 @@ mod test {
221182 fn test_make_header_value ( ) {
222183 let test_uuid_str = "37b56e4f-8c60-453b-a37e-99be6efe8a89" ;
223184 let test_uuid = test_uuid_str. parse :: < Uuid > ( ) . unwrap ( ) ;
224- let header_value = make_header_value ( ActorType :: Builtin , test_uuid) ;
185+ let header_value = make_header_value ( test_uuid) ;
225186 // Other formats are valid here (e.g., changes in case or spacing).
226187 // However, a black-box test that accounted for those would be at least
227188 // as complicated as `make_header_value()` itself and wouldn't be so
228189 // convincing in demonstrating that that function does what we think it
229190 // does.
230- assert_eq ! (
231- header_value. 0 . encode( ) . to_str( ) . unwrap( ) ,
232- "Bearer oxide-spoof-builtin-37b56e4f-8c60-453b-a37e-99be6efe8a89"
233- ) ;
234-
235- let header_value = make_header_value ( ActorType :: Silo , test_uuid) ;
236191 assert_eq ! (
237192 header_value. 0 . encode( ) . to_str( ) . unwrap( ) ,
238193 "Bearer oxide-spoof-37b56e4f-8c60-453b-a37e-99be6efe8a89"
@@ -245,7 +200,7 @@ mod test {
245200 let test_uuid = test_uuid_str. parse :: < Uuid > ( ) . unwrap ( ) ;
246201 assert_eq ! (
247202 make_header_value_raw( test_uuid_str. as_bytes( ) ) . unwrap( ) ,
248- make_header_value( ActorType :: Silo , test_uuid) . 0 . encode( ) ,
203+ make_header_value( test_uuid) . 0 . encode( ) ,
249204 ) ;
250205
251206 assert_eq ! (
@@ -272,29 +227,18 @@ mod test {
272227 fn test_spoof_header_valid ( ) {
273228 let test_uuid_str = "37b56e4f-8c60-453b-a37e-99be6efe8a89" ;
274229 let test_uuid = test_uuid_str. parse :: < Uuid > ( ) . unwrap ( ) ;
230+ let test_header = make_header_value ( test_uuid) ;
275231
276- // Success casees: the client provided a valid uuid in the header.
277- for actor_type in [ ActorType :: Builtin , ActorType :: Silo ] {
278- let test_header = make_header_value ( actor_type, test_uuid) ;
279- let success_case = authn_spoof ( Some ( & test_header) ) ;
280- match success_case {
281- SchemeResult :: Authenticated ( details) => {
282- assert_eq ! ( details. actor. actor_id( ) , test_uuid) ;
283- let found_type = details. actor . actor_type ( ) ;
284- match found_type {
285- db:: model:: IdentityType :: UserBuiltin => {
286- assert_eq ! ( actor_type, ActorType :: Builtin ) ;
287- }
288- db:: model:: IdentityType :: SiloUser => {
289- assert_eq ! ( actor_type, ActorType :: Silo ) ;
290- }
291- }
292- }
293- result => {
294- panic ! ( "unexpectedly failed authentication: {:?}" , result) ;
295- }
296- } ;
297- }
232+ // Success case: the client provided a valid uuid in the header.
233+ let success_case = authn_spoof ( Some ( & test_header) ) ;
234+ match success_case {
235+ SchemeResult :: Authenticated ( details) => {
236+ assert_eq ! ( details. actor. actor_id( ) , test_uuid) ;
237+ }
238+ _ => {
239+ assert ! ( false ) ;
240+ }
241+ } ;
298242 }
299243
300244 #[ test]
@@ -335,8 +279,7 @@ mod test {
335279 ] ;
336280
337281 for input in & bad_inputs {
338- let test_header =
339- make_header_value_str ( ActorType :: Builtin , input) . unwrap ( ) ;
282+ let test_header = make_header_value_str ( input) . unwrap ( ) ;
340283 let result = authn_spoof ( Some ( & test_header) ) ;
341284 if let SchemeResult :: Failed ( error) = result {
342285 assert ! ( error. to_string( ) . starts_with(
0 commit comments