private static async Task <User> GetGoogleUserInfo(ExternalLoginDetails externalLoginInfo) { ExternalEmailSecret googleSecrets = AppConst.Settings.ExternalLoginSecrets.FindObj(e => e.Provider.EqualCurrentCultureIgnoreCase("Google")); var caller = new HttpClient(); var content = new StringContent($"client_id={googleSecrets?.ClientId}&client_secret={googleSecrets?.ClientSecret}&code={externalLoginInfo.Code}&grant_type=authorization_code&redirect_uri={externalLoginInfo.RedirectUrl.ToLower()}"); content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded"); // get the token from github API by using the provided "code", "state", "clientId" and "clientSecret". var tokenResult = await caller.PostAsync("https://oauth2.googleapis.com/token", content).ConfigureAwait(false); var tokenResultArray = JsonConvert.DeserializeObject <dynamic>(await tokenResult.Content.ReadAsStringAsync().ConfigureAwait(false)); string tokenType = tokenResultArray.token_type; string accessToken = tokenResultArray.access_token; // Add the authorization information from the response above caller.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(tokenType, accessToken); caller.DefaultRequestHeaders.Add("User-Agent", "OSnack"); // get the user info by calling the github API with the above authorization var userInfoResult = await caller.GetAsync($"https://www.googleapis.com/oauth2/v2/userinfo").ConfigureAwait(false); var userInfoResultString = await userInfoResult.Content.ReadAsStringAsync().ConfigureAwait(false); var userInfoObj = JsonConvert.DeserializeObject <dynamic>(userInfoResultString); return(new User { Email = (string)userInfoObj.email, FirstName = (string)userInfoObj.given_name, Surname = (string)userInfoObj.family_name, RegistrationMethod = new RegistrationMethod { ExternalLinkedId = (string)userInfoObj.id, RegisteredDate = DateTime.UtcNow, Type = externalLoginInfo.Type, } }); }
private static async Task <User> GetFacebookUserInfo(ExternalLoginDetails externalLoginInfo) { ExternalEmailSecret facebookSecrets = AppConst.Settings.ExternalLoginSecrets.FindObj(e => e.Provider.EqualCurrentCultureIgnoreCase("Facebook")); var caller = new HttpClient(); // get the token from github API by using the provided "code", "state", "clientId" and "clientSecret". var tokenResult = await caller.GetAsync($"https://graph.facebook.com/v7.0/oauth/access_token?client_id={facebookSecrets?.ClientId}&redirect_uri={externalLoginInfo.RedirectUrl}&client_secret={facebookSecrets?.ClientSecret}&code={externalLoginInfo.Code}").ConfigureAwait(false); var tokenResultArray = JsonConvert.DeserializeObject <dynamic>(await tokenResult.Content.ReadAsStringAsync().ConfigureAwait(false)); string tokenType = tokenResultArray.token_type; string accessToken = tokenResultArray.access_token; // Add the authorization information from the response above caller.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(tokenType, accessToken); caller.DefaultRequestHeaders.Add("User-Agent", "OSnack"); // get the user info by calling the github API with the above authorization var userInfoResult = await caller.GetAsync($"https://graph.facebook.com/me?fields=id,email,first_name,last_name&access_token={accessToken}").ConfigureAwait(false); var userInfoResultString = await userInfoResult.Content.ReadAsStringAsync().ConfigureAwait(false); var userInfoObj = JsonConvert.DeserializeObject <dynamic>(userInfoResultString); return(new User { FirstName = (string)userInfoObj.first_name, Surname = (string)userInfoObj.last_name, Email = (string)userInfoObj.email, RegistrationMethod = new RegistrationMethod { ExternalLinkedId = (string)userInfoObj.id, RegisteredDate = DateTime.UtcNow, Type = externalLoginInfo.Type, } }); }
public async Task <IActionResult> ExternalLogin(ExternalLoginDetails externalLoginInfo) { try { IEnumerable <string> policies = AppFunc.GetCurrentRequestPolicies(Request, out AppTypes apptype); if (apptype == AppTypes.Invalid) { CoreFunc.Error(ref ErrorsList, "Unauthorised Application Access. 🤔"); return(Unauthorized(ErrorsList)); } if (!TryValidateModel(externalLoginInfo)) { CoreFunc.ExtractErrors(ModelState, ref ErrorsList); return(UnprocessableEntity(ErrorsList)); } User externalLoginUser = new User(); switch (externalLoginInfo.Type) { case RegistrationTypes.Google: externalLoginUser = await GetGoogleUserInfo(externalLoginInfo).ConfigureAwait(false); break; case RegistrationTypes.Facebook: externalLoginUser = await GetFacebookUserInfo(externalLoginInfo).ConfigureAwait(false); break; } // Check if the user is already registered User registeredUser = await _DbContext.Users .Include(u => u.Role) .Include(u => u.RegistrationMethod) .SingleOrDefaultAsync(u => u.RegistrationMethod.Type == externalLoginInfo.Type && u.RegistrationMethod.ExternalLinkedId == externalLoginUser.RegistrationMethod.ExternalLinkedId) .ConfigureAwait(false); // if the user is already registered if (registeredUser != null) { if (!await IsUserPolicyAccepted(registeredUser, policies).ConfigureAwait(false)) { CoreFunc.Error(ref ErrorsList, "You do not have permission to login here."); return(Unauthorized(ErrorsList)); } // sign the user in without any password await _SignInManager.SignInAsync(registeredUser, externalLoginInfo.RememberMe).ConfigureAwait(false); return(Ok(registeredUser)); } if (apptype == AppTypes.Admin) { CoreFunc.Error(ref ErrorsList, "You do not have permission to login here. Please contact administrator."); return(Unauthorized(ErrorsList)); } /// check if the user is registered using other methods User user = await _UserManager .FindByEmailAsync(externalLoginUser?.Email).ConfigureAwait(false); if (user != null) { RegistrationMethod registrationMethod = await _DbContext.RegistrationMethods .FirstOrDefaultAsync(r => r.User.Id == user.Id).ConfigureAwait(false); if (registrationMethod.Type != RegistrationTypes.Application) { /// in the case any exceptions return the following error CoreFunc.Error(ref ErrorsList, $"Please use {registrationMethod.Type} account to login."); } else { /// in the case any exceptions return the following error CoreFunc.Error(ref ErrorsList, $"Please use Email and Password to login"); } return(StatusCode(403, ErrorsList)); } externalLoginUser.Role = await _DbContext.Roles.FirstOrDefaultAsync(r => r.Name == "Customer").ConfigureAwait(false); // else if the user is not registered but information is received from external login externalLoginUser.Id = -1; return(StatusCode(206, externalLoginUser)); } catch (Exception ex) { CoreFunc.Error(ref ErrorsList, _LoggingService.LogException(Request.Path, ex, User)); return(StatusCode(417, ErrorsList)); } }