public async Task <IHttpActionResult> HandleResponseFromApple() { try { // TODO should probably check state here (and in the non-Apple one) InitialTokenResponse response = new InitialTokenResponse(); response.code = HttpContext.Current.Request.Form["code"]; response.user = HttpContext.Current.Request.Form["user"]; response.state = HttpContext.Current.Request.Form["state"]; //use state as client's requested return uri // Create a new instance of AppleAuthProvider AppleAuthProvider provider = new AppleAuthProvider( ConfigurationManager.AppSettings["oauth:apple:id"], ConfigurationManager.AppSettings["oauth:apple:teamid"], ConfigurationManager.AppSettings["oauth:apple:keyid"], //"https://webhook.site/cb4691d4-fdaf-4250-8613-a9ed1623453b",// string.Format("https://{0}/api/account/HandleResponseFromApple", Request.RequestUri.Authority), response.state); // Retrieve an authorization token AuthorizationToken authorizationToken = await provider.GetAuthorizationToken(response.code, ConfigurationManager.AppSettings["oauth:apple:secret"]); var login = new UserLoginInfo("Apple", authorizationToken.UserInformation.UserID); ApplicationUser user = await UserManager.FindAsync(login); if (user == null && string.IsNullOrWhiteSpace(response.user)) { // new user but apple didn't give details return(InternalServerError(new Exception("Something went wrong while getting your details from Apple. Please remove OurPlace from your 'Sign in with Apple' security settings and try again."))); } // apple only returns the user's details on the first authentication if (user == null && !string.IsNullOrWhiteSpace(response.user)) { dynamic appleUser = JsonConvert.DeserializeObject(response.user); user = new ApplicationUser { UserName = appleUser.email, Email = appleUser.email, FirstName = appleUser.name.firstName, Surname = appleUser.name.lastName, DateCreated = DateTime.UtcNow, AuthProvider = "Apple", Trusted = false, LastConsent = DateTime.UtcNow }; ApplicationUser existingResult = await UserManager.FindByEmailAsync(user.Email); if (existingResult == null) { // New user IdentityResult createResult = await UserManager.CreateAsync(user); if (!createResult.Succeeded) { return(GetErrorResult(createResult)); } } else { // user already exists with that email user.Id = existingResult.Id; await UserManager.UpdateAsync(user); } // Add this oauth login to the user account IdentityResult idResult = await UserManager.AddLoginAsync(user.Id, login); if (!idResult.Succeeded) { return(GetErrorResult(idResult)); } } else { // existing user Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie); } ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager, OAuthDefaults.AuthenticationType); ClaimsIdentity cookieIdentity = await user.GenerateUserIdentityAsync(UserManager, CookieAuthenticationDefaults.AuthenticationType); AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.UserName); properties = await AddRefreshToken(oAuthIdentity, properties); Authentication.SignIn(properties, oAuthIdentity, cookieIdentity); user.LastConsent = DateTime.UtcNow; await UserManager.UpdateAsync(user); Dictionary <string, string> args = new Dictionary <string, string>() { { "grant_type", "refresh_token" }, { "refresh_token", properties.Dictionary["refresh_token"] } }; RefreshResponse refResp; using (var client = new HttpClient()) { HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, string.Format("https://{0}/Token", Request.RequestUri.Authority)) { Content = new FormUrlEncodedContent(args) }; HttpResponseMessage resp = await client.SendAsync(req); if (resp.Content == null || !resp.IsSuccessStatusCode) { throw new Exception("Couldn't get an access token"); } string json = await resp.Content.ReadAsStringAsync(); refResp = JsonConvert.DeserializeObject <RefreshResponse>(json); } return(Redirect(string.Format("{0}#access_token={1}&token_type=bearer&expires_in={2}&refresh_token={3}&refresh_token_expires={4}", response.state, refResp.Access_token, refResp.Expires_in, properties.Dictionary["refresh_token"], properties.Dictionary["refresh_token_expires"]))); } catch (Exception e) { Console.WriteLine(e.Message); return(InternalServerError(new Exception(string.Format("HandleResponseFromApple\nkey{2}\n{0}\n{1}", e.Message, e.StackTrace, ConfigurationManager.AppSettings["oauth:apple:secret"])))); } }
public async Task <ActionResult> HandleResponseFromApple(InitialTokenResponse response) { try { // TODO should probably check state here but MVC seems to have different session IDs for each request yay // Create a new instance of AppleAuthProvider AppleAuthProvider provider = new AppleAuthProvider( ConfigurationManager.AppSettings["oauth:apple:id"], ConfigurationManager.AppSettings["oauth:apple:teamid"], ConfigurationManager.AppSettings["oauth:apple:keyid"], string.Format("https://{0}/account/HandleResponseFromApple", Request.Url.Authority), Session.SessionID); // Retrieve an authorization token AuthorizationToken authorizationToken = await provider.GetAuthorizationToken(response.code, ConfigurationManager.AppSettings["oauth:apple:secret"]); var login = new UserLoginInfo("Apple", authorizationToken.UserInformation.UserID); ApplicationUser user = await UserManager.FindAsync(login); // apple only returns the user's details on the first authentication if (user == null && !string.IsNullOrWhiteSpace(response.user)) { dynamic appleUser = JsonConvert.DeserializeObject(response.user); ApplicationUser appUser = new ApplicationUser { UserName = appleUser.email, Email = appleUser.email, FirstName = appleUser.name.firstName, Surname = appleUser.name.lastName, DateCreated = DateTime.UtcNow, AuthProvider = "Apple", Trusted = false, LastConsent = DateTime.UtcNow }; ApplicationUser existingResult = await UserManager.FindByEmailAsync(appUser.Email); if (existingResult == null) { // New user IdentityResult createResult = await UserManager.CreateAsync(appUser); if (!createResult.Succeeded) { return(RedirectToAction("Login")); } } else { // user already exists with that email appUser = existingResult; } // Add this oauth login to the user account IdentityResult idResult = await UserManager.AddLoginAsync(appUser.Id, login); if (!idResult.Succeeded) { return(RedirectToAction("Login")); } ClaimsIdentity oAuthIdentity = await appUser.GenerateUserIdentityAsync(UserManager, OAuthDefaults.AuthenticationType); ClaimsIdentity cookieIdentity = await appUser.GenerateUserIdentityAsync(UserManager, CookieAuthenticationDefaults.AuthenticationType); AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(appUser.UserName); await SignInManager.SignInAsync(appUser, true, true); Request.GetOwinContext().Authentication.SignIn(properties, oAuthIdentity, cookieIdentity); return(RedirectToLocal("/")); } else if (user != null) { // existing user ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager, OAuthDefaults.AuthenticationType); ClaimsIdentity cookieIdentity = await user.GenerateUserIdentityAsync(UserManager, CookieAuthenticationDefaults.AuthenticationType); AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.UserName); Request.GetOwinContext().Authentication.SignIn(properties, oAuthIdentity, cookieIdentity); user.LastConsent = DateTime.UtcNow; await UserManager.UpdateAsync(user); return(RedirectToLocal("/")); } else { // new user but apple didn't give details // TODO show instructions for removing ourplace from your apple account so that it can be re-added ViewData["errormessage"] = "Something went wrong while getting your details from Apple. Please remove OurPlace from your 'Sign in with Apple' security settings and try again."; return(View("Error")); } } catch (Exception e) { Console.WriteLine(e.Message); ViewData["errormessage"] = string.Format("HandleResponseFromApple\nkey{2}\n{0}\n{1}", e.Message, e.StackTrace, ConfigurationManager.AppSettings["oauth:apple:secret"]); return(View("Error")); } }