I am trying to get user hometown and location using Facebook graph API for the logged-in user
Public permissions to fetch location and hometown is granted by the user.
Graph API version v2.8
/me?fields=name,picture,location,hometown
You need to ask for permissions: user_hometown and user_location. The hometown/location is not included in the public permissions.
You can also check the scope of your access token here
Here is how you can get the complete user profile using FB token:
I am assuming you have given permission before getting token from graph api explore which is:
https://developers.facebook.com/tools/explorer/
public Profile GetProfile(string facebookID)
{
var url = "?fields=first_name,last_name,name,age_range,birthday, education, gender, hometown, locale, location, third_party_id, timezone, email";
dynamic result = _facebookClient.Get(facebookID + url);
var profile = new Profile();
if (result != null)
{
string resultStringify = result.ToString();
var resultBlock = JObject.Parse(resultStringify);
//if (result.ToString().Contains("first_name")) {
// profile.First_Name = resultBlock["first_name"].ToString();
//}
profile.First_Name = resultStringify.ExtractIfValueIsAvailable("first_name", resultBlock);
//if (result.ToString().Contains("last_name")) {
// profile.Last_Name = resultBlock["last_name"].ToString();
//}
profile.Last_Name = resultStringify.ExtractIfValueIsAvailable("last_name", resultBlock);
//if (result.ToString().Contains("name")) {
// profile.Name = resultBlock["name"].ToString();
//}
profile.Name = resultStringify.ExtractIfValueIsAvailable("name", resultBlock);
if (result.ToString().Contains("age_range"))
{
if (result.age_range.min != null) profile.Age_Range_Min = result.age_range.min;
if (result.age_range.max != null) profile.Age_Range_Max = result.age_range.max;
}
//if (result.ToString().Contains("birthday")) {
// profile.Birthday = DateTime.ParseExact(result.birthday, "MM/dd/yyyy", CultureInfo.InvariantCulture);
//}
profile.Birthday = resultStringify.ExtractIfDateTime("birthday", resultBlock);
//if (result.ToString().Contains("gender")) {
// profile.Gender = resultBlock["gender"].ToString();
//}
profile.Gender = resultStringify.ExtractIfValueIsAvailable("gender", resultBlock);
//if (result.ToString().Contains("hometown")) {
// profile.Hometown = resultBlock["hometown"]["name"].ToString();
//}
profile.Hometown = resultStringify.ExtractIfNameValueIsAvailable("hometown", resultBlock);
//if (result.ToString().Contains("locale")) {
// profile.Locale = resultBlock["locale"].ToString();
//}
profile.Locale = resultStringify.ExtractIfValueIsAvailable("locale", resultBlock);
//if (result.ToString().Contains("location")) {
// profile.Location = resultBlock["location"]["name"].ToString();
//}
profile.Location = resultStringify.ExtractIfNameValueIsAvailable("location", resultBlock);
//if (result.ToString().Contains("third_party_id")) {
// profile.Third_Party_ID = resultBlock["third_party_id"].ToString();
//}
profile.Third_Party_ID = resultStringify.ExtractIfValueIsAvailable("third_party_id", resultBlock);
profile.Timezone = resultStringify.ExtractIfValueIsAvailable("timezone", resultBlock);
profile.EMail = resultStringify.ExtractIfValueIsAvailable("email", resultBlock);
}
return profile;
}
public static string ExtractIfValueIsAvailable(this string result, string fieldName, dynamic resultBlock) => result.Contains(fieldName) ? resultBlock[fieldName].ToString() : string.Empty;
Hope it helps.
Related
This is controller code. Here I have provide how I'm creating enterprise. But currently I'm unable to create enterprise without enterprise token. Which I'm getting from customer, when customer registering thyself on play.google.com.
<!-- begin snippet: js hide: false console: true babel: false -->
using Google.Apis.Auth.AspNetCore3;
using Google.Apis.Auth.OAuth2;
using Google.Apis.AndroidManagement.v1;
using Google.Apis.Services;
using Microsoft.AspNetCore.Mvc;
using Google.Apis.AndroidManagement.v1.Data;
using System.Security.Claims;
using Newtonsoft.Json;
using QRCoder;
using System.Drawing;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using IHostingEnvironment = Microsoft.AspNetCore.Hosting.IHostingEnvironment;
namespace xProducts_RETL.Web.Controllers
{
public class EmmController : Controller
{
private readonly ILoggerManager _loggerManager;
private readonly IEmmMapper _iEmmMapper;
private readonly IConfiguration _iConfiguration;
private SignInManager<IdentityUser> _signInManager;
private readonly RoleManager<IdentityRole> _roleManager;
private readonly IHostingEnvironment _environment;
private readonly UserManager<IdentityUser> _userManager;
//private static readonly string ProjectId = "xpdemo";
private static readonly string ProjectId = "xdemo";
private static readonly string PolicyId = Zoo_ManagedPolicy";
private static readonly string PolicyId2 = "Zoo_WorkPolicy";
private static readonly string PolicyId3 = "Zoo_ManagedPolicyx";
//private static readonly string COSU_APP_PACKAGE_NAME = "com.google.android.apps.work.clouddpc";
//private static readonly string TestEnterpriseName = "enterprises/xxxxj";
private static readonly string TestEnterpriseName = "enterprises/xxxx8";
private const string Package_Outlook = "com.microsoft.office.outlook";
public EmmController(ILoggerManager loggermanager, IEmmMapper iEmmMapper, IConfiguration iConfiguration, SignInManager<IdentityUser> signInManager, RoleManager<IdentityRole> roleManager, UserManager<IdentityUser> userManager,IHostingEnvironment environment)
{
_loggerManager = loggermanager;
_iEmmMapper = iEmmMapper;
_iConfiguration = iConfiguration;
_signInManager = signInManager;
_userManager = userManager;
_roleManager = roleManager;
_environment = environment;
}
[HttpGet]
public IActionResult CreateEnterprise(EnterpriseDto enterpriseDto, string x)
{
try
{
//bind dropdowns
enterpriseDto.EnterpriseList = _iEmmMapper.GetEnterpriseList();
enterpriseDto.CreatedEnterpriseList = _iEmmMapper.GetGooglePlaySignedupEnterpriseList();
//fetch superadmin info
var superadminData = _userManager.GetUsersInRoleAsync("SuperAdmin").Result;
var superadminId = superadminData[0].Id;
var enterpriseList = _iEmmMapper.GetEnterprises().Where(x => x.OwnerIdentityId == superadminId && x.EnrollmentToken != null && x.EnrollmentTokenWP != null).ToList();
foreach (var enterprise in enterpriseList)
{
enterpriseDto.EnterpriseId = enterprise.EnterpriseId;
}
//
return View(enterpriseDto);
}
catch (Exception ex)
{
_loggerManager.LogError($"Something went wrong inside CreateEnterprise get action: {ex.Message}");
return View(enterpriseDto);
}
}
[HttpPost]
public IActionResult CreateEnterprise(EnterpriseDto enterpriseObj)
{
//populate default dropdown values
EnterpriseDto enterpriseModel = new();
enterpriseModel.EnterpriseList = _iEmmMapper.GetEnterpriseList();
enterpriseModel.CreatedEnterpriseList = _iEmmMapper.GetEnterpriseList();
if (enterpriseObj.Id != 0 || enterpriseObj.Id2 != 0)
{
#region serviceAccountAuthenctiactionFlow
//read service a/c creds
ServiceAccountCredential? credential;
string fileName = "service_account_key.json";
string path = Path.Combine(this._environment.WebRootPath, "ZeroTouchCredJSON", fileName);
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
credential = GoogleCredential.FromStream(stream)
.CreateScoped("https://www.googleapis.com/auth/androidmanagement")
.UnderlyingCredential as ServiceAccountCredential;
}
// Create a zero-touch enrollment API service endpoint.
var service = new AndroidManagementService(new BaseClientService.Initializer
{
HttpClientInitializer = credential,
ApplicationName = ResourceMsg.EMMAppName
});
#endregion
//create signup url
var signupData = service.SignupUrls.Create();
signupData.ProjectId = ProjectId;
signupData.CallbackUrl = _iConfiguration.GetValue<string>("AppSetting:CallBackURL");
var response = signupData.Execute();
if (response != null)
{
//create enterprise
var enterpriseData = service.Enterprises.Create(new Enterprise());
enterpriseData.ProjectId = ProjectId;
enterpriseData.SignupUrlName = response.Name;
enterpriseData.EnterpriseToken = "EAJmqckyhc_cep8KkQ-NDU3SG4uC7WfJk1oumRM9SqDPZ-jzMY6D-K-bbWaYHMDvMNsc-faLjwLdyF50yTZIKv_JK_vxEXxp2rPVKkDxzce8whACXz261yaM";
var enterpriseResponse = enterpriseData.Execute();
}
}
return View(enterpriseModel);
}
//[GoogleScopedAuthorize(AndroidManagementService.ScopeConstants.Androidmanagement)]
//[HttpPost]
//public async Task<IActionResult> CreateEnterprise([FromServices] IGoogleAuthProvider auth, EnterpriseDto enterpriseObj)
//{
// EnterpriseDto enterpriseModel = new();
// try
// {
// //bind dropdowns
// enterpriseModel.EnterpriseList = _iEmmMapper.GetEnterpriseList();
// enterpriseModel.CreatedEnterpriseList = _iEmmMapper.GetEnterpriseList();
// if (enterpriseObj.Id != 0 || enterpriseObj.Id2 != 0)
// {
// #region OAuthFlow
// // Check if the required scopes have been granted.
// if (await auth.RequireScopesAsync(AndroidManagementService.ScopeConstants.Androidmanagement) is IActionResult authResult)
// {
// return authResult;
// }
// //The required scopes have now been granted.
// GoogleCredential cred = await auth.GetCredentialAsync();
// var service = new AndroidManagementService(new BaseClientService.Initializer
// {
// HttpClientInitializer = cred.CreateScoped(AndroidManagementService.Scope.Androidmanagement),
// ApplicationName = ResourceMsg.EMMAppName
// });
// //Fetch client information from GCP
// dynamic name = "";
// dynamic email = "";
// if (User.Identity is ClaimsIdentity claimsIdentity)
// {
// var listk = claimsIdentity.Claims.Select(x => new { x.Type, x.Value }).ToList();
// name = listk[3].Value;
// email = User.FindFirstValue(ClaimTypes.Email);
// }
// //noob | superadmin
// if (email != "xy#gmail.com")
// {
// TempData["VerificationFailed"] = "You have logged in with a customer account. Please login with owner account to continue.";
// return View();
// }
// //var enterpriseRes = _iEmmMapper.GetEnterprises().Where(x=> x.ClientEmail == email);
// //if(enterpriseRes!= null)
// //{
// // TempData["MsgSignupFailed"] = "There is already an Enterprise exist. Please try with a different mail to add a new Enterprise.";
// // return View(enterpriseModel);
// //}
// #endregion
// //check userId existance
// string ownerUserId = "";
// var users = _userManager.Users.ToList();
// foreach (var user in users)
// {
// if (user.Email == "xx#yopmail.com")
// {
// ownerUserId = user.Id;
// break;
// }
// }
// //Enterprise Signup
// if (enterpriseObj.Id != 0 && enterpriseObj.ActionFlag == "Signup")
// {
// //create signup url
// var signupData = service.SignupUrls.Create();
// signupData.AccessToken = cred.UnderlyingCredential.GetAccessTokenForRequestAsync().Result;
// signupData.ProjectId = ProjectId;
// signupData.CallbackUrl = _iConfiguration.GetValue<string>("AppSetting:CallBackURL");
// //signupData.Service.
// var response = signupData.Execute();
// var ownerGoogleAccountId = User.FindFirstValue(ClaimTypes.Email);
// if (ownerGoogleAccountId != null && ownerUserId != null)
// {
// //assign client info to model
// enterpriseObj.ClientName = name;
// enterpriseObj.ClientEmail = email;
// //assign signup data to vmodel
// enterpriseObj.SignupUrlName = response.Name;
// enterpriseObj.SignupUrlURL = response.Url;
// enterpriseObj.OwnerIdentityId = ownerUserId;
// enterpriseObj.OwnerGoogleAccountId = ownerGoogleAccountId;
// //insert data into database
// var result = _iEmmMapper.CreateUpdateEnterprise(enterpriseObj);
// if (result == 1)
// {
// TempData["MsgSignupUrl"] = "Signup URL for the enterprise generated successfully.";
// return View(enterpriseModel);
// }
// }
// TempData["VerificationFailed"] = "Please login with current account details.";
// return View(enterpriseModel);
// }
// //Create Enterprise
// if (enterpriseObj.Id2 != 0 && enterpriseObj.ActionFlag == "Enterprise")
// {
// var response = _iEmmMapper.GetEnterprises().Where(x => x.Id == enterpriseObj.Id2).FirstOrDefault();
// if (response != null)
// {
// var enterpriseData = service.Enterprises.Create(new Enterprise());
// enterpriseData.AccessToken = cred.UnderlyingCredential.GetAccessTokenForRequestAsync().Result;
// enterpriseData.ProjectId = ProjectId;
// enterpriseData.SignupUrlName = response.SignupUrlName;
// enterpriseData.EnterpriseToken = response.EnterpriseToken;
// //enterprise generated
// var enterpriseResponse = enterpriseData.Execute();
// enterpriseModel.EnterpriseNameAPIFormat = enterpriseResponse.Name;
// var EnterpriseNameResponse = enterpriseResponse.Name;
// //enterpriseModel.EnterpriseToken = enterpriseData.EnterpriseToken;
// //fetch enterprise from db
// //var resultEnterprise = _iEmmMapper.GetEnterprises();
// //if (resultEnterprise != null)
// //{
// // foreach (var enterprise in resultEnterprise)
// // {
// //if (enterprise.ClientEmail == email)
// //{
// //prepare commonpolicies obj
// CommonPoliciesDto commonPolicies = new();
// //initialize model to assign apps into it
// commonPolicies.ApplicationDtoList = new List<ApplicationsDto>();
// var appModel = new ApplicationsDto();
// //enterprise Id >noob
// string[] enterpriseFullId = enterpriseResponse.Name.Split('/');
// string enterpriseId = enterpriseFullId[1];
// //create two different new policies
// string[] enterpriseArr = response.EnterpriseNameRequested.Split(' ');
// string enterpriseFirstName = enterpriseArr[0];
// string ManagedProfilePolicyName = enterpriseFirstName + "_FMDefaultPolicy";
// string WorkProfilePolicyName = enterpriseFirstName + "_WPDefaultPolicy";
// //var IsPolicyIdExist = _iEmmMapper.GetDevices().Where(x => x.PolicyId == PolicyId3 && x.EnterpriseId == enterpriseId).Any();//noob
// //if (IsPolicyIdExist)
// //{
// // SetDefaultPoliciesForExistingPolicy(TestEnterpriseName, PolicyId3);
// //}
// //else
// //{
// // //if policyId not assigned previously with any token
// // GenereateEnrollmentTokenForNewPolicy(TestEnterpriseName, PolicyId3);
// //}
// var IsManagedPolicyIdExist = _iEmmMapper.GetCommonPolicies().Where(x => x.PolicyId == ManagedProfilePolicyName && x.EnterpriseId == enterpriseId).Any();//noob
// if (!IsManagedPolicyIdExist)
// {
// //if policyId not assigned previously with any token
// GenereateEnrollmentTokenForNewPolicy(EnterpriseNameResponse, ManagedProfilePolicyName, ResourceMsg.FullyManged);
// }
// var IsWorkPolicyIdExist = _iEmmMapper.GetCommonPolicies().Where(x => x.PolicyId == WorkProfilePolicyName && x.EnterpriseId == enterpriseId).Any();//noob
// if (!IsWorkPolicyIdExist)
// {
// //if policyId not assigned previously with any token
// GenereateEnrollmentTokenForNewPolicy(EnterpriseNameResponse, WorkProfilePolicyName, ResourceMsg.Work);
// }
// #region localFunctionToGenerateTokenThruEnterpriseIdAndPolicyId
// void GenereateEnrollmentTokenForNewPolicy(string enterpriseNameAPIFormat, string myPolicyId, string policyProfileType)
// {
// //forming policy name
// string policyName = enterpriseNameAPIFormat + ResourceMsg.POLICIES_FORMAT + myPolicyId;
// //set a default hardware policy to newly registered device
// var appliedPolicyData = service.Enterprises.Policies.Patch(DefaultHardwarePolicies(myPolicyId), policyName).Execute();
// if (appliedPolicyData != null)//noob
// {
// enterpriseModel.PolicyName = policyName;
// //Create Default Policy in Database
// CommonPoliciesDto commonPoliciesModel = new()
// {
// UserIdentityId = ownerUserId,
// EnterpriseId = enterpriseId,
// PolicyId = myPolicyId,
// PolicyName = policyName,
// PolicyType = "Default",
// PolicyProfileType = policyProfileType,
// PolicyNameApiFormat = policyName,
// //
// MaximumTimeToLock = 0,
// StatusBarDisabled = false,
// KeyguardDisabled = false,
// WifiConfigDisabled = false,
// MobileNetworksConfigDisabled = false,
// BluetoothDisabled = true,
// BluetoothContactSharingDisabled = true,
// UsbFileTransferDisabled = true,
// AdjustVolumeDisabled = true,
// ScreenCaptureDisabled = true,
// ShareLocationDisabled = true,
// AutoDateAndTimeZone = ResourceMsg.AUTO_DATEANDTIMEZONE_UNSPECIFIED,
// CameraDisabled = true
// };
// var result = _iEmmMapper.CreateUpdateCommonPolicies(commonPoliciesModel);
// if (result == 0)
// {
// //TempData["MsgCmnPolicies"] = ResourceMsg.PoliciesCreatedSuccessfully;
// }
// var rtrvPolicy6 = _iEmmMapper.GetCommonPolicies().ToList();
// var rtrvPolicy = _iEmmMapper.GetCommonPolicies().Where(x => x.PolicyId == myPolicyId).FirstOrDefault();
// if (rtrvPolicy != null)
// {
// if (rtrvPolicy.PolicyProfileType == ResourceMsg.FullyManged)
// {
// //create enrollmentToken for Fully Managed Device with a policy name & assign created user
// //removed to setup KIOSK mode -> .SetUser(user.AccountIdentifier)
// EnrollmentToken token = new DemoEnrollmentToken().SetPolicyName(myPolicyId).SetDuration(ResourceMsg.ThirtyDaysInSecond).SetAllowPersonalUsage(ResourceMsg.PERSONAL_USAGE_DISALLOWED);
// var tokenResponse = service.Enterprises.EnrollmentTokens.Create(token, enterpriseNameAPIFormat).Execute();
// var eToken = tokenResponse.Value;
// enterpriseModel.EnrollmentToken = eToken;
// }
// else
// {
// if (rtrvPolicy.PolicyProfileType == ResourceMsg.Work)
// {
// //User setup [can't be use in KIOSK mode setup or only work for work profile]
// var user = new User
// {
// AccountIdentifier = Guid.NewGuid().ToString()
// };
// //create enrollmentToken for work profile Device with a policy name & assign created user
// EnrollmentToken token2 = new DemoEnrollmentToken().SetPolicyName(myPolicyId).SetUser(user.AccountIdentifier).SetDuration(ResourceMsg.ThirtyDaysInSecond).SetAllowPersonalUsage(ResourceMsg.PERSONAL_USAGE_ALLOWED);
// var tokenResponse2 = service.Enterprises.EnrollmentTokens.Create(token2, enterpriseNameAPIFormat).Execute();
// var eToken2 = tokenResponse2.Value;
// enterpriseModel.EnrollmentTokenWP = eToken2;
// }
// }
// }
// else
// {
// _loggerManager.LogError($"There is an error occured in GenereateEnrollmentTokenForNewPolicy local function. {ResourceMsg.InvalidPolicy}");
// TempData["Failure"] = ResourceMsg.InvalidPolicy;
// }
// }
// }
// #endregion
// enterpriseModel.Id = enterpriseObj.Id2;
// enterpriseModel.EnterpriseId = enterpriseId;
// if (enterpriseModel.Id != 0 && enterpriseModel.EnterpriseId != null)
// {
// //update data into database
// var entResponse = _iEmmMapper.CreateUpdateEnterprise(enterpriseModel);
// if (entResponse == 1)
// {
// TempData["MsgEnterprise"] = ResourceMsg.EnterpriseCreatedSuccessfully;
// }
// }
// //}
// // }
// //}
// }
// else
// {
// TempData["Failure"] = ResourceMsg.ContactTechnicalTeam;
// }
// }
// }
// return View(enterpriseModel);
// }
// catch (Google.GoogleApiException gex)
// {
// string msgErr = "Error in " + this.GetType().ToString();
// _loggerManager.LogError($"{msgErr}{gex.Message}");
// TempData["Failure"] = ResourceMsg.ContactTechnicalTeam;
// return View(enterpriseModel);
// }
// catch (Exception ex)
// {
// string msgErr = "Error in " + this.GetType().ToString();
// _loggerManager.LogError($"{msgErr}{ex.Message}");
// TempData["Failure"] = ResourceMsg.ContactTechnicalTeam;
// return View(enterpriseModel);
// }
//}
I'm facing this issue from a long time. Please share your feedback and help on this. Any help is appreciable.
There are two ways to create an enterprise:
Customer-managed enterprise: This is the recommended way to create an enterprise. This is the one you are using in your code and it requires an enterprise token.
EMM-managed enterprise: This is not the preferred method to create an enterprise, but it is still possible to create and manage an EMM-managed enterprise using this method. EMM managed enterprises can be created programmatically without customer intervention.
This guide covers how to create EMM-managed enterprises. With this method, EMMs have full control over an enterprise’s lifecycle.
Note: In the future, it would not be possible to create any EMM-managed enterprises using the enterprises.create method.
I suggest reviewing the process of creating a Customer-managed Enterprise by having the Enterprise IT admin complete the sign-up flow, as this is the preferred method.
I have been using facebook login for one of my asp.net core projects. However, it stopped working for Facebook login suddenly. I am getting HTTP 500 error.
The issue is, even in the debug more, asp.net core is not mentioning any error. It is just same 500 error code. Nothing else.
When I tried to set breakpoint in the first line of public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null) function, I realized that it is not even hitting that and failing even before that.
I am not sure how to debug this further. Am I missing anything here? Or is there any change from FB in the login side?
The return URL being hit is by Facebook is:
https://localhost:44300/signin-facebook?code=AQBxGGw7ZCoa9xtXc3CCsVGRD9TJLL428bZ_eJpUu4CtVu3K4UrfOZuYYdwFBXzGZ6GOGXpOi2Nme_jfbewB84otVZhKZfs4i7Dhi9Y3E_rloU9ouLeIvuOsm29jr7IDCtTj_HM7rKuKjj3zmc4yz5i_fniZ9ZhMfXtSus5KyKa4EFkZTsmKrz2ngMlGQalUAob_52GJNhvSIXDlmiNSrZLJV3m7Zbkf9eXETQkqhu2L1kgXPvWkMzVP8EN00GwRCYB3xT1kQMOimDANRKhziZjoVS5QZFUJTP0Faj47tE1xNfmAzb30iuwcaRORCOTMipUrnRvOO4nGRo8JuUNdPJaO&state=CfDJ8EHIO3qHMHFClr5BAt4EC1Wj7LyAs5Pg1XOqKo4uFiJM2Jr1rNyooxLIu2fbXr6Z3X5_kqbF_7WwFfvF3L3H4xgyooo-3Y9BV8Zh1S5wXlLJDAyCT5_LwkPJ1j8Zrwx4umQJp6NOl76GwRXpi1_BHlWGRxnh_naTL35iqeGovOa8oEDC0jOQ4trRe7YG3fV_ptjWk4yOnvJnsI81O-6wfyhdc3jm-LTP7ZO7-duf_lPZXZ8mL42XyLXDTIyOJ__S2yLYdvwItdDVntsM8Hwq94goXdU-RaH7ZkDA8iAzeCl3Ke0tWAdYBKy9vooJIXmE9Q#_=_
Based on this article, it should have state_token too in the URL. But that seems to be missing here. How can I figure out here what is the actual error?
I am using asp.net core RC2 release.
My callback function is:
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null)
{
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
return RedirectToAction(nameof(Login));
}
// Sign in the user with this external login provider if the user already has a login.
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false);
if (result.Succeeded)
{
_logger.LogInformation(5, "User logged in with {Name} provider.", info.LoginProvider);
return RedirectToLocal(returnUrl);
}
if (result.RequiresTwoFactor)
{
return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl });
}
if (result.IsLockedOut)
{
return View("Lockout");
}
else
{
// If the user does not have an account, then ask the user to create an account.
ViewData["ReturnUrl"] = returnUrl;
ViewData["LoginProvider"] = info.LoginProvider;
var email = info.ExternalPrincipal.FindFirstValue(ClaimTypes.Email);
if (email == null)
{
return View("Error");
}
/* Determine user from external login info */
var name = info.ExternalPrincipal.FindFirstValue(ClaimTypes.Name);
string firstName;
string lastName = "";
if (!string.IsNullOrWhiteSpace(name))
{
firstName = name.Split(' ').Length > 1? name.Split(new[] { ' ' }, 2)[0] : name;
lastName = name.Split(' ').Length > 1 ? name.Split(new[] { ' ' }, 2)[1] : "";
}
else
firstName = email.Split('#')[0];
var user = await _userManager.FindByEmailAsync(email);
if (user == null)
{
/* No user with same email ID. So, create a new user.*/
var newUser = new ApplicationUser
{
UserName = email,
Email = email,
FirstName = firstName,
LastName = lastName,
PasswordLastModifiedTime = DateTime.UtcNow,
UserSignUpDate = DateTime.UtcNow
};
var userCreationResult = await _userManager.CreateAsync(newUser);
if (userCreationResult.Succeeded)
{
userCreationResult = await _userManager.AddLoginAsync(newUser, info);
if (userCreationResult.Succeeded)
{
// Add user claims TODO:// Test if the claims are added successfully.
await _userManager.AddClaimAsync(newUser, new Claim("FirstName", newUser.FirstName));
await _userManager.AddClaimAsync(newUser, new Claim("LastName", newUser.LastName));
// Set user email to confirmed. This is more of work around
var code = await _userManager.GenerateEmailConfirmationTokenAsync(newUser);
userCreationResult = await _userManager.ConfirmEmailAsync(newUser, code);
if (userCreationResult.Succeeded)
{
//Create Subscription for user
var planService = new PlanServices();
var plan = planService.Find((int)SubscriptionType.Basic);
await _subscriptionService.CreateSubscription(newUser, plan, null);
await _signInManager.SignInAsync(newUser, isPersistent: false);
_logger.LogInformation(6, "User created an account using {Name} provider.",
info.LoginProvider);
await _emailSender.SendWelcomeEmailAsync(newUser.Email, newUser.FirstName);
return RedirectToLocal(returnUrl);
}
}
}
}
else
{
/* A user with email ID exists. Associate the account with that.*/
var loginAddResult = await _userManager.AddLoginAsync(user, info);
if (loginAddResult.Succeeded)
{
await _signInManager.SignInAsync(user, isPersistent: false);
return RedirectToLocal(returnUrl);
}
}
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email, FirstName = firstName, LastName = lastName});
}
}
And ConfigureServices method is:
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddApplicationInsightsTelemetry(Configuration);
services.AddScoped<ApplicationDbContext>();
services.AddIdentity<ApplicationUser, IdentityRole>(o =>
{
o.Password.RequireDigit = false;
o.Password.RequireLowercase = false;
o.Password.RequireUppercase = false;
o.Password.RequireNonLetterOrDigit = false;
o.Password.RequiredLength = 8;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddCaching();
services.AddSession();
services.AddMvc();
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
services.AddTransient<ISubscriptionService, SubscriptionService>();
services.Configure<AuthMessageSenderOptions>(Configuration);
services.Configure<RecaptchaOptions>(Configuration);
__serviceProvider = services.BuildServiceProvider();
}
The thing is, it worked well for a long time and has stopped working now. Also, it is not even hitting ExternalLoginCallback, so I am not sure where to head for debugging it further.
I am having issue in confirming new user email. the Confirm email link works for first 20 minutes , but after 50 minutes the link expires. I have set the token expiration time to 24 hours. Please help me in resolving this issue. I am stuck on it for last 2 days:(.My code is as follows:
I am setting the token lifetime in Create() method in ApplicationUserManager as following:
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
userManager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"))
{
TokenLifespan = _settings.ConfirmationAndResetTokenExpirationTimeSpan
};
}
And then In AccountsController, the Create method for new user is geiven below. The SendEmailAsync method consist of email subject, email body, generated password and the callback uri.
[Authorize(Roles = Roles.Bam.Name.Admin)]
[HttpPost]
[Route(Routes.Accounts.Template.Create, Name = Routes.Accounts.Name.Create)]
public async Task<IHttpActionResult> Create(CreateUserBindingModel createUserBindingModel)
{
IHttpActionResult result;
var memberNameExists = UserManager.Users.Any(x => x.MemberName.ToLower() == createUserBindingModel.MemberName.ToLower());
if (!memberNameExists)
{
var applicationUser = new ApplicationUser
{
UserName = createUserBindingModel.Email,
Email = createUserBindingModel.Email,
FirstName = createUserBindingModel.FirstName,
LastName = createUserBindingModel.LastName,
Company = createUserBindingModel.Company,
Location = createUserBindingModel.Location,
PhoneNumber = createUserBindingModel.PhoneNumber,
MemberName = createUserBindingModel.MemberName,
LastLoginDate = SqlDateTime.MinValue.Value,
CreateDate = DateTime.Now,
CreatedBy = User.Identity.GetUserId(),
UpdateDate = DateTime.Now,
UpdatedBy = User.Identity.GetUserId(),
TwoFactorEnabled = createUserBindingModel.TwoFactorEnabled,
SecurityResetRequired = true,
PasswordExpirationDate = DateTime.Now.AddDays(Convert.ToDouble(ConfigurationManager.AppSettings["PasswordExpirationDays"]))
};
if (!string.IsNullOrEmpty(createUserBindingModel.AvatarBase64))
{
var avatarBytes = Convert.FromBase64String(createUserBindingModel.AvatarBase64);
var resizedAvatarBytes = ImageResizer.ResizeImage(avatarBytes, _avatarWidth, _avatarHeight);
applicationUser.UserAvatar = new ApplicationUserAvatar
{
Avatar = resizedAvatarBytes
};
}
var generatedPassword = PasswordGenerator.GenerateStrongPassword(10, 10);
var identityResult = await UserManager.CreateAsync(applicationUser, generatedPassword);
if (identityResult.Succeeded)
{
await UserManager.AddToRolesAsync(applicationUser.Id, createUserBindingModel.Roles.ToArray());
var token = await UserManager.GenerateEmailConfirmationTokenAsync(applicationUser.Id);
var callbackUri = string.Format("{0}?userId={1}&token={2}", createUserBindingModel.EmailConfirmationCallbackUri, applicationUser.Id, HttpUtility.UrlEncode(token));
await UserManager.SendEmailAsync(applicationUser.Id, Email.Confirmation.Subject, string.Format(Email.Confirmation.Body, string.Format("{0} {1}", applicationUser.FirstName, applicationUser.LastName), callbackUri, generatedPassword, _settings.AccessTokenExpirationTimeSpan.TotalHours));
var userUrl = new Uri(Url.Link(Routes.Accounts.Name.Get, new { id = applicationUser.Id }));
var roles = await UserManager.GetRolesAsync(applicationUser.Id);
var contract = _accountsMapper.ToContract(applicationUser, roles);
result = Created(userUrl, contract);
}
else
{
result = GetErrorResult(identityResult);
}
}
else
{
ModelState.AddModelError(string.Empty, "Member Name already exists!");
result = BadRequest(ModelState);
}
return result;
}
Once the email is generated the UI has following JS angular code which gets executed and the provide the userid and token to service.
Angular JS code:
angular.module('confirmEmailModule').factory('confirmEmailFactory', function ($http) {
var factory = {};
factory.confirmEmail = function(userId, token) {
var encodedToken = encodeURIComponent(token);
var uri = '/identity/api/accounts/confirmemail?userId=' + userId + '&token=' + token;
return $http.post(uri);
}
return factory;
});
and the Service is :
[AllowAnonymous]
[HttpPost]
[Route(Routes.Accounts.Template.ConfirmEmail, Name = Routes.Accounts.Name.ConfirmEmail)]
public async Task<IHttpActionResult> ConfirmEmail([FromUri] string userId, [FromUri] string token)
{
//var decodedToken = HttpUtility.UrlDecode(token);
var identityResult = await UserManager.ConfirmEmailAsync(userId, token);
var result = identityResult.Succeeded ? StatusCode(HttpStatusCode.NoContent) : GetErrorResult(identityResult);
return result;
}
Please advice.
I found the solution to this issue. I am posting it if somebody faced the same issue. In my case the services and web API were on different servers. Different machine keys caused this issue. So I generated the machine key for my Web application and posted the same machine key in web.config file of Identity service. After that it worked. For more information on generating machine key, following link is helpful.
http://gunaatita.com/Blog/How-to-Generate-Machine-Key-using-IIS/1058
This is what worked for me. Hope it helps out;
public async Task<IActionResult> ConfirmEmail(string userId, string token)
{
if (userId == null || token == null)
{
return RedirectToAction("employees", "home");
}
var user = await userManager.FindByIdAsync(userId);
if (user == null)
{
ViewBag.ErrorMessage = $"The User ID {userId} is invalid";
return View("NotFound");
}
var result = await userManager.ConfirmEmailAsync(user, Uri.EscapeDataString(token));
if (result != null)
{
user.EmailConfirmed = true;
await userManager.UpdateAsync(user);
return View();
}
}
I tried to make an authorization in my asp with my git client, so my git client will be requested an authorization from my server. When i tried to send a request to my git client, it was showing an error
repository http://localhost/git/user/try.git/info/ref not found
Here is my routeconfig
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
#region remoteURL
routes.MapRoute(
name: "RemoteURL",
url: "git/{project}.git/{*verb}",
defaults: new { controller = "Git", action = "Smart" }
);
routes.MapRoute(
name: "Git",
url: "git/{project}/{*verb}",
defaults: new { controller = "Git", action = "Smart" }
);
#endregion
#region Account;
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
#endregion;
}
and this is my controller that use an attribute :
public class GitController : Controller
{
[SmartGit]
public ActionResult Smart(string project, string service, string verb)
{
switch (verb)
{
case "info/refs":
return InfoRefs(project, service);
case "git-upload-pack":
return ExecutePack(project, "git-upload-pack");
case "git-receive-pack":
return ExecutePack(project, "git-receive-pack");
default:
return RedirectToAction("Tree", "Repository", new { Name = project });
}
}
and then this is my attribute smartgit
public class SmartGitAttribute : SmartAuthorizeAttribute
{
private const string AuthKey = "GitCodeGitAuthorize";
private GitCodeContext db = new GitCodeContext();
private string project;
private string verb;
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
var right = false;
var userfound = false;
List<string> paramParsing = new List<string>();
//url.Split("")
//base.OnAuthorization(filterContext);
var controller = filterContext.Controller as GitController;
if (controller == null)
return;
// git.exe not accept cookies as well as no session available
var auth = controller.HttpContext.Request.Headers["Authorization"];
if (!String.IsNullOrEmpty(auth))
{
var bytes = Convert.FromBase64String(auth.Substring(6));
var certificate = Encoding.ASCII.GetString(bytes);
var index = certificate.IndexOf(':');
var password = certificate.Substring(index + 1);
var username = certificate.Substring(0, index);
//var user = controller.MembershipService.Login(username, password);
if (WebSecurity.Login(username, password))
{
WebSecurity.Login(username, password);
userfound = true;
}
}
var projectField = controller.ValueProvider.GetValue("project");
var serviceField = controller.ValueProvider.GetValue("service");
var verbField = controller.ValueProvider.GetValue("service");
//filterContext.Controller.ValueProvider
var project = projectField == null ? null : projectField.AttemptedValue;
var service = serviceField == null ? null : serviceField.AttemptedValue;
var verb = verbField == null ? null : serviceField.AttemptedValue;
if (string.IsNullOrEmpty(service) && userfound) // redirect to git browser
{
right = true;
}
else if (string.Equals(service, "git-receive-pack", StringComparison.OrdinalIgnoreCase) && userfound) // git push
{
//right = controller.RepositoryService.CanWriteRepository(project, username);
right = true;
}
else if (string.Equals(service, "git-upload-pack", StringComparison.OrdinalIgnoreCase) && userfound ) // git fetch
{
//right = controller.RepositoryService.CanReadRepository(project, username);
right = true;
}
if (!userfound)
{
if (WebSecurity.CurrentUserName == "")
{
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.AddHeader("WWW-Authenticate", "Basic realm=\"coba\"");
filterContext.Result = new HttpUnauthorizedResult();
}
else
{
throw new UnauthorizedAccessException();
}
}
}
I found my own mistake, maybe my response doesn't have enough information so i decide to add a few information in my SmartGitAttribute
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.StatusDescription = "Unauthorized";
filterContext.HttpContext.Response.AddHeader("WWW-Authenticate", "Basic realm=\"Secure Area\"");
filterContext.HttpContext.Response.Write("401, please authenticate");
filterContext.HttpContext.Response.StatusCode = 401;
filterContext.Result = new EmptyResult();
filterContext.HttpContext.Response.End();
this is reference that can help you to solve response authentication
with Facebook C# sdk I read signed_request and have following details
if (Request.Params["signed_request"] != null)
{
dynamic signedRequest = fb.ParseSignedRequest(ConfigHelper.FacebookAppSecret,
Request.Params["signed_request"]);
Session["signedRequest"] = signedRequest.ToString();
if (signedRequest.page != null)
{
requestFromFanPage = true;
var lPid = signedRequest.page.id != null ? (string) signedRequest.page.id : "";
Session["lPid"] = lPid.ToString();
var lLiked = signedRequest.page.liked ?? "";
Session["lLiked"] = lLiked;
userLiked = lLiked;
}
var userid = signedRequest.user_id ?? "";
Session["lUserId"] = userid;
}
and I get following result without Facebook id :(
{"algorithm":"HMAC-SHA256","issued_at":1370416053,"page":{"id":"490007204401534","liked":true,"admin":false},"user":{"country":"au","locale":"en_US","age":{"min":21}}}
I need facebookuserid , Is there any way that I can get it with out getting permission?