@@ -129,19 +129,19 @@ impl FxAClient for Client {
129129 }
130130
131131 // For the one-off generation of a `refresh_token` and associated meta from transient credentials.
132-
133132 fn refresh_token_with_code (
134133 & self ,
135134 config : & Config ,
136135 code : & str ,
137136 code_verifier : & str ,
138137 ) -> Result < OAuthTokenResponse > {
139- let body = json ! ( {
140- "code" : code,
141- "client_id" : config. client_id,
142- "code_verifier" : code_verifier
143- } ) ;
144- self . make_oauth_token_request ( config, body)
138+ let req_body = OAauthTokenRequest :: UsingCode {
139+ code : code. to_string ( ) ,
140+ client_id : config. client_id . to_string ( ) ,
141+ code_verifier : code_verifier. to_string ( ) ,
142+ ttl : None ,
143+ } ;
144+ self . make_oauth_token_request ( config, serde_json:: to_value ( req_body) . unwrap ( ) )
145145 }
146146
147147 fn refresh_token_with_session_token (
@@ -173,11 +173,10 @@ impl FxAClient for Client {
173173 ttl : Option < u64 > ,
174174 scopes : & [ & str ] ,
175175 ) -> Result < OAuthTokenResponse > {
176- let req = OAuthTokenRequest {
176+ let req = OAauthTokenRequest :: UsingRefreshToken {
177177 client_id : config. client_id . clone ( ) ,
178- grant_type : String :: from ( "refresh_token" ) ,
179178 refresh_token : refresh_token. to_string ( ) ,
180- scope : scopes. join ( " " ) ,
179+ scope : Some ( scopes. join ( " " ) ) ,
181180 ttl,
182181 } ;
183182 self . make_oauth_token_request ( config, serde_json:: to_value ( req) . unwrap ( ) )
@@ -661,14 +660,30 @@ pub struct DeviceResponseCommon {
661660 pub push_endpoint_expired : bool ,
662661}
663662
663+ // We model the OAuthTokenRequest according to the up to date
664+ // definition on
665+ // https://github.com/mozilla/fxa/blob/8ae0e6876a50c7f386a9ec5b6df9ebb54ccdf1b5/packages/fxa-auth-server/lib/oauth/routes/token.js#L70-L152
666+
664667#[ derive( Serialize ) ]
665- pub struct OAuthTokenRequest {
666- pub client_id : String ,
667- pub grant_type : String ,
668- pub refresh_token : String ,
669- pub scope : String ,
670- #[ serde( skip_serializing_if = "Option::is_none" ) ]
671- pub ttl : Option < u64 > ,
668+ #[ serde( tag = "grant_type" ) ]
669+ enum OAauthTokenRequest {
670+ #[ serde( rename = "refresh_token" ) ]
671+ UsingRefreshToken {
672+ client_id : String ,
673+ refresh_token : String ,
674+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
675+ scope : Option < String > ,
676+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
677+ ttl : Option < u64 > ,
678+ } ,
679+ #[ serde( rename = "authorization_code" ) ]
680+ UsingCode {
681+ client_id : String ,
682+ code : String ,
683+ code_verifier : String ,
684+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
685+ ttl : Option < u64 > ,
686+ } ,
672687}
673688
674689#[ derive( Deserialize ) ]
@@ -729,3 +744,28 @@ pub struct DuplicateTokenResponse {
729744 #[ serde( rename = "authAt" ) ]
730745 pub auth_at : u64 ,
731746}
747+
748+ #[ cfg( test) ]
749+ mod tests {
750+ use super :: * ;
751+
752+ #[ test]
753+ #[ allow( non_snake_case) ]
754+ fn check_OAauthTokenRequest_serialization ( ) {
755+ // Ensure OAauthTokenRequest serializes to what the server expects.
756+ let using_code = OAauthTokenRequest :: UsingCode {
757+ code : "foo" . to_owned ( ) ,
758+ client_id : "bar" . to_owned ( ) ,
759+ code_verifier : "bobo" . to_owned ( ) ,
760+ ttl : None ,
761+ } ;
762+ assert_eq ! ( "{\" grant_type\" :\" authorization_code\" ,\" client_id\" :\" bar\" ,\" code\" :\" foo\" ,\" code_verifier\" :\" bobo\" }" , serde_json:: to_string( & using_code) . unwrap( ) ) ;
763+ let using_code = OAauthTokenRequest :: UsingRefreshToken {
764+ client_id : "bar" . to_owned ( ) ,
765+ refresh_token : "foo" . to_owned ( ) ,
766+ scope : Some ( "bobo" . to_owned ( ) ) ,
767+ ttl : Some ( 123 ) ,
768+ } ;
769+ assert_eq ! ( "{\" grant_type\" :\" refresh_token\" ,\" client_id\" :\" bar\" ,\" refresh_token\" :\" foo\" ,\" scope\" :\" bobo\" ,\" ttl\" :123}" , serde_json:: to_string( & using_code) . unwrap( ) ) ;
770+ }
771+ }
0 commit comments