@@ -7,6 +7,7 @@ use oauth2::{
77 url:: form_urlencoded:: parse,
88} ;
99use secrecy:: SecretString ;
10+ use serde_json:: Value ;
1011use shield:: {
1112 ConfigurationError , CreateEmailAddress , CreateUser , Form , MethodAction , MethodSession , Request ,
1213 RequestMethod , Response , ResponseType , SessionAction , ShieldError , SignInCallbackAction ,
@@ -221,14 +222,46 @@ impl<U: User + 'static> MethodAction<OauthProvider, OauthSession> for OauthSignI
221222 . await
222223 . map_err ( |err| ShieldError :: Request ( err. to_string ( ) ) ) ?;
223224
224- // TODO: user info
225- let identifier = "" ;
226- let email = Some ( "" ) ;
227- let name = Some ( "" ) ;
225+ let user_response = async_http_client
226+ . get ( & provider. user_url )
227+ . bearer_auth ( token_response. access_token ( ) . secret ( ) )
228+ . send ( )
229+ . await
230+ . map_err ( |err| ShieldError :: Request ( err. to_string ( ) ) ) ?;
231+
232+ let user = user_response
233+ . json :: < Value > ( )
234+ . await
235+ . map_err ( |err| ShieldError :: Request ( err. to_string ( ) ) ) ?;
236+
237+ let user = if let Some ( user_path) = & provider. user_path {
238+ value_by_path ( & user, user_path) ?
239+ } else {
240+ & user
241+ } ;
242+
243+ let identifier = value_by_path ( user, & provider. user_id_path ) ?;
244+ let identifier = identifier
245+ . as_str ( )
246+ . map ( ToOwned :: to_owned)
247+ . or_else ( || identifier. as_number ( ) . map ( |number| number. to_string ( ) ) )
248+ . ok_or_else ( || ShieldError :: Request ( "Missing or invalid user ID." . to_owned ( ) ) ) ?;
249+
250+ let email = if let Ok ( email) = value_by_path ( user, & provider. user_email_path ) {
251+ email. as_str ( )
252+ } else {
253+ None
254+ } ;
255+
256+ let name = if let Ok ( name) = value_by_path ( user, & provider. user_name_path ) {
257+ name. as_str ( )
258+ } else {
259+ None
260+ } ;
228261
229262 let ( connection, user) = match self
230263 . storage
231- . oauth_connection_by_identifier ( & provider. id , identifier)
264+ . oauth_connection_by_identifier ( & provider. id , & identifier)
232265 . await ?
233266 {
234267 Some ( connection) => {
@@ -310,3 +343,19 @@ fn parse_token_response(
310343 . map ( |scopes| scopes. iter ( ) . map ( |scope| scope. to_string ( ) ) . collect ( ) ) ,
311344 ) )
312345}
346+
347+ fn value_by_path < ' a > ( data : & ' a Value , path : & str ) -> Result < & ' a Value , ShieldError > {
348+ let mut data = data;
349+
350+ for key in path. split ( "." ) {
351+ if let Some ( value) = data. get ( key) {
352+ data = value;
353+ } else {
354+ return Err ( ShieldError :: Request ( format ! (
355+ "Path `{path}` not found in JSON response."
356+ ) ) ) ;
357+ }
358+ }
359+
360+ Ok ( data)
361+ }
0 commit comments