/// <summary> /// Creates or Finds a Person and UserLogin record, and returns the userLogin.UserName /// </summary> /// <param name="auth0UserInfo">The auth0 user information.</param> /// <returns></returns> public static string GetAuth0UserName(Auth0UserInfo auth0UserInfo) { string username = string.Empty; string userName = "******" + auth0UserInfo.sub; UserLogin user = null; using (var rockContext = new RockContext()) { // Query for an existing user var userLoginService = new UserLoginService(rockContext); user = userLoginService.GetByUserName(userName); // If no user was found, see if we can find a match in the person table if (user == null) { // Get name/email from auth0 userinfo string lastName = auth0UserInfo.family_name?.Trim()?.FixCase(); string firstName = auth0UserInfo.given_name?.Trim()?.FixCase(); string nickName = auth0UserInfo.nickname?.Trim()?.FixCase(); string email = auth0UserInfo.email; Person person = null; // If person had an email, get the first person with the same name and email address. if (!string.IsNullOrWhiteSpace(email)) { var personService = new PersonService(rockContext); var people = personService.GetByMatch(firstName, lastName, email); if (people.Count() == 1) { person = people.First(); } } var personRecordTypeId = DefinedValueCache.Read(SystemGuid.DefinedValue.PERSON_RECORD_TYPE_PERSON.AsGuid()).Id; var personStatusPending = DefinedValueCache.Read(SystemGuid.DefinedValue.PERSON_RECORD_STATUS_PENDING.AsGuid()).Id; rockContext.WrapTransaction(() => { if (person == null) { person = new Person(); person.IsSystem = false; person.RecordTypeValueId = personRecordTypeId; person.RecordStatusValueId = personStatusPending; person.FirstName = firstName; person.LastName = lastName; person.Email = email; person.IsEmailActive = true; person.EmailPreference = EmailPreference.EmailAllowed; if (auth0UserInfo.gender == "male") { person.Gender = Gender.Male; } else if (auth0UserInfo.gender == "female") { person.Gender = Gender.Female; } else { person.Gender = Gender.Unknown; } if (person != null) { PersonService.SaveNewPerson(person, rockContext, null, false); } } if (person != null) { int typeId = EntityTypeCache.Read(typeof(Auth0Authentication)).Id; user = UserLoginService.Create(rockContext, person, AuthenticationServiceType.External, typeId, userName, "auth0", true); user.ForeignKey = auth0UserInfo.sub; } }); } if (user != null) { username = user.UserName; if (user.PersonId.HasValue) { var personService = new PersonService(rockContext); var person = personService.Get(user.PersonId.Value); if (person != null) { // If person does not have a photo, try to get the photo return with auth0 if (!person.PhotoId.HasValue && !string.IsNullOrWhiteSpace(auth0UserInfo.picture)) { // Download the photo from the url provided var restClient = new RestClient(auth0UserInfo.picture); var restRequest = new RestRequest(Method.GET); var restResponse = restClient.Execute(restRequest); if (restResponse.StatusCode == HttpStatusCode.OK) { var bytes = restResponse.RawBytes; // Create and save the image BinaryFileType fileType = new BinaryFileTypeService(rockContext).Get(Rock.SystemGuid.BinaryFiletype.PERSON_IMAGE.AsGuid()); if (fileType != null) { var binaryFileService = new BinaryFileService(rockContext); var binaryFile = new BinaryFile(); binaryFileService.Add(binaryFile); binaryFile.IsTemporary = false; binaryFile.BinaryFileType = fileType; binaryFile.MimeType = restResponse.ContentType; binaryFile.FileName = user.Person.NickName + user.Person.LastName + ".jpg"; binaryFile.FileSize = bytes.Length; binaryFile.ContentStream = new System.IO.MemoryStream(bytes); rockContext.SaveChanges(); person.PhotoId = binaryFile.Id; rockContext.SaveChanges(); } } } } } } return(username); } }
/// <summary> /// Authenticates the user based on a request from a third-party provider. Will set the username and returnUrl values. /// </summary> /// <param name="request">The request.</param> /// <param name="userName">Name of the user.</param> /// <param name="returnUrl">The return URL.</param> /// <returns></returns> public override bool Authenticate(System.Web.HttpRequest request, out string userName, out string returnUrl) { string authDomain = this.GetAttributeValue("ClientDomain"); string clientId = this.GetAttributeValue("ClientID"); string clientSecret = this.GetAttributeValue("ClientSecret"); userName = string.Empty; returnUrl = request.QueryString["state"]; string code = request.QueryString["code"]; string redirectUri = GetRedirectUrl(request); // see: https://auth0.com/docs/api/authentication#support var restClient = new RestClient($"https://{authDomain}"); var authTokenRequest = new RestRequest("oauth/token", Method.POST); var authTokenRequestBody = new { grant_type = "authorization_code", client_id = clientId, client_secret = clientSecret, code, redirect_uri = redirectUri }; authTokenRequest.AddJsonBody(authTokenRequestBody); var authTokenRestResponse = restClient.Execute(authTokenRequest); if (authTokenRestResponse.StatusCode == HttpStatusCode.OK) { Auth0TokenResponse authTokenResponse = authTokenRestResponse.Content.FromJsonOrNull <Auth0TokenResponse>(); if (authTokenResponse != null) { var userInfoRequest = new RestRequest($"userinfo?access_token={authTokenResponse.access_token}", Method.GET); var userInfoRestResponse = restClient.Execute(userInfoRequest); if (userInfoRestResponse.StatusCode == HttpStatusCode.OK) { Auth0UserInfo auth0UserInfo = userInfoRestResponse.Content.FromJsonOrNull <Auth0UserInfo>(); var managementTokenRequest = new RestRequest("oauth/token", Method.POST); var managementTokenRequestBody = new { grant_type = "client_credentials", client_id = clientId, client_secret = clientSecret, audience = $"https://{authDomain}/api/v2/" }; managementTokenRequest.AddJsonBody(managementTokenRequestBody); var managementTokenRestResponse = restClient.Execute(managementTokenRequest); if (managementTokenRestResponse.StatusCode == HttpStatusCode.OK) { Auth0TokenResponse managementTokenResponse = managementTokenRestResponse.Content.FromJsonOrNull <Auth0TokenResponse>(); var managementUserLookupRequest = new RestRequest($"api/v2/users/{auth0UserInfo.sub}", Method.GET); managementUserLookupRequest.AddHeader("authorization", $"Bearer {managementTokenResponse?.access_token}"); var managementUserLookupResponse = restClient.Execute(managementUserLookupRequest); if (managementUserLookupResponse.StatusCode == HttpStatusCode.OK) { // if we were able to look up the user using the management api, fill in null given_name from user_metadata or app_metadata; var managementUserInfo = managementUserLookupResponse.Content.FromJsonOrNull <Auth0ManagementUserInfo>(); if (managementUserInfo != null) { if (auth0UserInfo.given_name == null) { auth0UserInfo.given_name = managementUserInfo.user_metadata?.given_name ?? managementUserInfo.app_metadata?.given_name; // if we had to get given_name from user_metadata/app_metadata, then the nickname that we got back might not be correct, so just have it be given_name auth0UserInfo.nickname = auth0UserInfo.given_name; } if (auth0UserInfo.family_name == null) { auth0UserInfo.family_name = managementUserInfo.user_metadata?.family_name ?? managementUserInfo.app_metadata?.family_name; } } } } userName = GetAuth0UserName(auth0UserInfo); return(true); } } } return(false); }