@@ -43,6 +43,7 @@ struct AuthFields {
4343 client_secret : String ,
4444 auth_url : String ,
4545 token_url : String ,
46+ userinfo_url : String ,
4647 redirect_url : String ,
4748 scopes : Vec < Scope > ,
4849}
@@ -74,6 +75,12 @@ fn parse_auth_fields(state: &mut State<'_>) -> Result<AuthFields, VmError> {
7475 . as_string ( )
7576 . unwrap ( )
7677 . to_string ( ) ;
78+ let userinfo_url = fields
79+ . get ( & state. intern_static ( "userinfo_url" ) )
80+ . unwrap ( )
81+ . as_string ( )
82+ . unwrap ( )
83+ . to_string ( ) ;
7784 let redirect_url = fields
7885 . get ( & state. intern_static ( "redirect_url" ) )
7986 . unwrap ( )
@@ -96,6 +103,7 @@ fn parse_auth_fields(state: &mut State<'_>) -> Result<AuthFields, VmError> {
96103 client_secret,
97104 auth_url,
98105 token_url,
106+ userinfo_url,
99107 redirect_url,
100108 scopes,
101109 } )
@@ -161,26 +169,41 @@ fn verify<'gc>(state: &mut State<'gc>, args: Vec<Value<'gc>>) -> Result<Value<'g
161169 let code = code
162170 . ok_or_else ( || VmError :: RuntimeError ( "verify() requires 'code' keyword argument" . into ( ) ) ) ?;
163171
164- let fields = parse_auth_fields ( state) ?;
172+ let mut fields = parse_auth_fields ( state) ?;
173+ let userinfo_url = mem:: take ( & mut fields. userinfo_url ) ;
165174
166175 let http_client = reqwest:: ClientBuilder :: new ( )
167176 // Following redirects opens the client up to SSRF vulnerabilities.
168177 . redirect ( reqwest:: redirect:: Policy :: none ( ) )
169178 . build ( )
170179 . expect ( "Client should build" ) ;
171180
172- let token = match Handle :: current ( ) . block_on ( async {
173- get_client ( fields)
181+ Handle :: current ( ) . block_on ( async {
182+ let token = get_client ( fields)
174183 . exchange_code ( AuthorizationCode :: new ( code. to_string ( ) ) )
175184 . request_async ( & http_client)
176185 . await
177- } ) {
178- Ok ( token) => token,
179- Err ( err) => return Err ( VmError :: RuntimeError ( err. to_string ( ) ) ) ,
180- } ;
181-
182- Ok ( Value :: IoString ( Gc :: new (
183- state,
184- token. access_token ( ) . secret ( ) . to_owned ( ) ,
185- ) ) )
186+ . map_err ( |err| VmError :: RuntimeError ( err. to_string ( ) ) ) ?;
187+ let access_token = token. access_token ( ) . secret ( ) . to_owned ( ) ;
188+
189+ let response = http_client
190+ . get ( userinfo_url)
191+ . header ( "Authorization" , format ! ( "Bearer {}" , access_token) )
192+ . send ( )
193+ . await
194+ . map_err ( |err| VmError :: RuntimeError ( err. to_string ( ) ) ) ?;
195+
196+ if !response. status ( ) . is_success ( ) {
197+ return Err ( VmError :: RuntimeError ( format ! (
198+ "Failed to fetch user info: {}" ,
199+ response. status( )
200+ ) ) ) ;
201+ }
202+
203+ let info = response
204+ . json :: < serde_json:: Value > ( )
205+ . await
206+ . map_err ( |err| VmError :: RuntimeError ( err. to_string ( ) ) ) ?;
207+ Ok ( Value :: from_serde_value ( state. get_context ( ) , & info) )
208+ } )
186209}
0 commit comments