private CookieAuthenticationEvents get_sams_authentication_events() { //https://stackoverflow.com/questions/52175302/handling-expired-refresh-tokens-in-asp-net-core var sams_endpoint_authorization = Configuration["sams:endpoint_authorization"]; var sams_endpoint_token = Configuration["sams:endpoint_token"]; var sams_endpoint_user_info = Configuration["sams:endpoint_user_info"]; var sams_endpoint_token_validation = Configuration["sams:token_validation"]; var sams_endpoint_user_info_sys = Configuration["sams:user_info_sys"]; var sams_client_id = Configuration["sams:client_id"]; var sams_client_secret = Configuration["sams:client_secret"]; var sams_callback_url = Configuration["sams:callback_url"]; var result = new CookieAuthenticationEvents { OnValidatePrincipal = context => { //check to see if user is authenticated first if (context.Principal.Identity.IsAuthenticated) { var expires_at = context.Request.Cookies["expires_at"]; var expires_at_time = DateTimeOffset.Parse(expires_at); /* * var accessToken = context.Request.HttpContext.Session.GetString("access_token"); * var refreshToken = context.Request.HttpContext.Session.GetString("refresh_token"); * var exp = context.Request.HttpContext.Session.GetInt32("expires_in"); */ /* * var tokens = context.Properties.GetTokens(); * var refreshToken = tokens.FirstOrDefault(t => t.Name == "refresh_token"); * var accessToken = tokens.FirstOrDefault(t => t.Name == "access_token"); * var exp = tokens.FirstOrDefault(t => t.Name == "expires_at"); * var expires = DateTime.Parse(exp.Value); */ //context.Request.Cookies.["sid"]. // var expires = DateTime.Parse(exp.ToString()); //check to see if the token has expired if (expires_at_time.DateTime < DateTime.Now) { try { var sid = context.Request.Cookies["sid"]; string request_string = Program.config_couchdb_url + $"/session/{sid}"; var curl = new cURL("GET", null, request_string, null, Program.config_timer_user_name, Program.config_timer_password); string session_json = curl.execute(); var session = Newtonsoft.Json.JsonConvert.DeserializeObject <mmria.common.model.couchdb.session> (session_json); var userName = context.Principal.Identities.First( u => u.IsAuthenticated && u.HasClaim(c => c.Type == ClaimTypes.Name)).FindFirst(ClaimTypes.Name).Value; if (!userName.Equals(session.user_id, StringComparison.OrdinalIgnoreCase)) { context.RejectPrincipal(); return(Task.CompletedTask); } var accessToken = session.data["access_token"]; var refreshToken = session.data["refresh_token"]; var exp = session.data["expires_at"]; expires_at_time = DateTimeOffset.Parse(exp); // server-side check for expiration if (expires_at_time.DateTime < DateTime.Now) { //token is expired, let's attempt to renew var tokenEndpoint = sams_endpoint_token; var tokenClient = new mmria.server.util.TokenClient(Configuration); //var name = HttpContext.Session.GetString(SessionKeyName); //var name = HttpContext.Session.GetString(SessionKeyName); var tokenResponse = tokenClient.get_refresh_token(accessToken.ToString(), refreshToken.ToString()).Result; //check for error while renewing - any error will trigger a new login. if (tokenResponse.is_error) { //reject Principal context.RejectPrincipal(); return(Task.CompletedTask); } //set new token values refreshToken = tokenResponse.refresh_token; accessToken = tokenResponse.access_token; var unix_time = DateTimeOffset.UtcNow.AddSeconds(tokenResponse.expires_in); session.data["access_token"] = accessToken; session.data["refresh_token"] = refreshToken; session.data["expires_at"] = unix_time.ToString(); context.Response.Cookies.Append("expires_at", unix_time.ToString()); session.date_last_updated = DateTime.UtcNow; var Session_Message = new mmria.server.model.actor.Session_Message ( session._id, //_id = session._rev, //_rev = session.date_created, //date_created = session.date_last_updated, //date_last_updated = session.date_expired, //date_expired = session.is_active, //is_active = session.user_id, //user_id = session.ip, //ip = session.session_event_id, // session_event_id = session.data ); Program.actorSystem.ActorOf(Props.Create <mmria.server.model.actor.Post_Session>()).Tell(Session_Message); //trigger context to renew cookie with new token values context.ShouldRenew = true; return(Task.CompletedTask); } } catch (Exception ex) { // do nothing for now document doesn't exsist. System.Console.WriteLine($"err caseController.Post\n{ex}"); } } } return(Task.CompletedTask); } }; return(result); }
public async Task <ActionResult> SignInCallback() { var sams_endpoint_authorization = _configuration["sams:endpoint_authorization"]; var sams_endpoint_token = _configuration["sams:endpoint_token"]; var sams_endpoint_user_info = _configuration["sams:endpoint_user_info"]; var sams_endpoint_token_validation = _configuration["sams:token_validation"]; var sams_endpoint_user_info_sys = _configuration["sams:endpoint_user_info_sys"]; var sams_client_id = _configuration["sams:client_id"]; var sams_client_secret = _configuration["sams:client_secret"]; var sams_callback_url = _configuration["sams:callback_url"]; //?code=6c17b2a3-d65a-44fd-a28c-9aee982f80be&state=a4c8326ca5574999aa13ca02e9384c3d // Retrieve code and state from query string, pring for debugging var querystring = Request.QueryString.Value; var querystring_skip = querystring.Substring(1, querystring.Length - 1); var querystring_array = querystring_skip.Split("&"); var querystring_dictionary = new Dictionary <string, string>(); foreach (string item in querystring_array) { var pair = item.Split("="); querystring_dictionary.Add(pair[0], pair[1]); } var code = querystring_dictionary["code"]; var state = querystring_dictionary["state"]; System.Diagnostics.Debug.WriteLine($"code: {code}"); System.Diagnostics.Debug.WriteLine($"state: {state}"); HttpClient client = new HttpClient(); var request = new HttpRequestMessage(HttpMethod.Post, sams_endpoint_token); /* * request.Content = new FormUrlEncodedContent(new Dictionary<string, string> { * { "client_id", sams_client_id }, * { "client_secret", sams_client_secret }, * { "grant_type", "client_credentials" }, * { "code", code }, * }); */ request.Content = new FormUrlEncodedContent(new Dictionary <string, string> { { "client_id", sams_client_id }, { "client_secret", sams_client_secret }, { "grant_type", "authorization_code" }, { "code", code }, { "scope", "openid profile email" }, { "redirect_uri", sams_callback_url } }); var response = await client.SendAsync(request); response.EnsureSuccessStatusCode(); var payload = JObject.Parse(await response.Content.ReadAsStringAsync()); var access_token = payload.Value <string>("access_token"); var refresh_token = payload.Value <string>("refresh_token"); var expires_in = payload.Value <int>("expires_in"); var scope = payload.Value <string>("scope"); //HttpContext.Session.SetString("access_token", access_token); //HttpContext.Session.SetString("refresh_token", refresh_token); var unix_time = DateTimeOffset.UtcNow.AddSeconds(expires_in); //HttpContext.Session.SetString("expires_at", unix_time.ToString()); var id_token = payload.Value <string>("id_token");; var id_array = id_token.Split('.'); var replaced_value = id_array[1].Replace('-', '+').Replace('_', '/'); var base64 = replaced_value.PadRight(replaced_value.Length + (4 - replaced_value.Length % 4) % 4, '='); var id_0 = DecodeToken(id_array[0]); var id_1 = DecodeToken(id_array[1]); var id_body = Base64Decode(base64); var user_info_sys_request = new HttpRequestMessage(HttpMethod.Post, sams_endpoint_user_info + "?token=" + id_token); user_info_sys_request.Headers.Add("Authorization", "Bearer " + access_token); user_info_sys_request.Headers.Add("client_id", sams_client_id); user_info_sys_request.Headers.Add("client_secret", sams_client_secret); /* * user_info_sys_request.Content = new FormUrlEncodedContent(new Dictionary<string, string> { * { "client_id", sams_client_id }, * { "client_secret", sams_client_secret }, * { "grant_type", "client_credentials" }, * { "scope", scope }, * }); */ response = await client.SendAsync(user_info_sys_request); response.EnsureSuccessStatusCode(); var temp_string = await response.Content.ReadAsStringAsync(); payload = JObject.Parse(temp_string); var email = payload.Value <string>("email"); //check if user exists var config_couchdb_url = _configuration["mmria_settings:couchdb_url"]; var config_timer_user_name = _configuration["mmria_settings:timer_user_name"]; var config_timer_password = _configuration["mmria_settings:timer_password"]; mmria.common.model.couchdb.user user = null; try { string request_string = config_couchdb_url + "/_users/" + System.Web.HttpUtility.HtmlEncode("org.couchdb.user:"******"GET", null, request_string, null, config_timer_user_name, config_timer_password); var responseFromServer = await user_curl.executeAsync(); user = Newtonsoft.Json.JsonConvert.DeserializeObject <mmria.common.model.couchdb.user>(responseFromServer); } catch (Exception ex) { Console.WriteLine(ex); } mmria.common.model.couchdb.document_put_response user_save_result = null; if (user == null)// if user does NOT exists create user with email { user = add_new_user(email.ToLower(), Guid.NewGuid().ToString()); try { Newtonsoft.Json.JsonSerializerSettings settings = new Newtonsoft.Json.JsonSerializerSettings(); settings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore; var object_string = Newtonsoft.Json.JsonConvert.SerializeObject(user, settings); string user_db_url = config_couchdb_url + "/_users/" + user._id; var user_curl = new mmria.server.cURL("PUT", null, user_db_url, object_string, config_timer_user_name, config_timer_password); var responseFromServer = await user_curl.executeAsync(); user_save_result = Newtonsoft.Json.JsonConvert.DeserializeObject <mmria.common.model.couchdb.document_put_response>(responseFromServer); } catch (Exception ex) { Console.WriteLine(ex); } } //create login session if (user_save_result == null || user_save_result.ok) { var session_data = new System.Collections.Generic.Dictionary <string, string>(StringComparer.InvariantCultureIgnoreCase); session_data["access_token"] = access_token; session_data["refresh_token"] = refresh_token; session_data["expires_at"] = unix_time.ToString(); await create_user_principal(user.name, new List <string>(), unix_time.DateTime); var Session_Event_Message = new mmria.server.model.actor.Session_Event_Message ( DateTime.Now, user.name, this.GetRequestIP(), mmria.server.model.actor.Session_Event_Message.Session_Event_Message_Action_Enum.successful_login ); _actorSystem.ActorOf(Props.Create <mmria.server.model.actor.Record_Session_Event>()).Tell(Session_Event_Message); var Session_Message = new mmria.server.model.actor.Session_Message ( Guid.NewGuid().ToString(), //_id = null, //_rev = DateTime.Now, //date_created = DateTime.Now, //date_last_updated = null, //date_expired = true, //is_active = user.name, //user_id = this.GetRequestIP(), //ip = Session_Event_Message._id, // session_event_id = session_data ); _actorSystem.ActorOf(Props.Create <mmria.server.model.actor.Post_Session>()).Tell(Session_Message); Response.Cookies.Append("sid", Session_Message._id); Response.Cookies.Append("expires_at", unix_time.ToString()); //return RedirectToAction("Index", "HOME"); //return RedirectToAction("Index", "HOME"); } return(RedirectToAction("Index", "HOME")); // Generate JWT for token request //var cert = new X509Certificate2(Server.MapPath("~/App_Data/cert.pfx"), "1234"); /* * var cert = new X509Certificate2(); * var signingCredentials = new SigningCredentials(new X509SecurityKey(cert), SecurityAlgorithms.RsaSha256); * var header = new JwtHeader(signingCredentials); * * var header = new JwtHeader(); * var payload = new JwtPayload * { * {"iss", sams_client_id}, * {"sub", sams_client_id}, * {"aud", $"{sams_endpoint_token}"}, * {"jti", Guid.NewGuid().ToString("N")}, * {"exp", (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds + 5 * 60} * }; * var securityToken = new JwtSecurityToken(header, payload); * var handler = new JwtSecurityTokenHandler(); * var tokenString = handler.WriteToken(securityToken); * * // Send POST to make token request * using (var wb = new WebClient()) * { * var data = new NameValueCollection(); * data["client_assertion"] = tokenString; * data["client_assertion_type"] = HttpUtility.HtmlEncode("urn:ietf:params:oauth:client-assertion-type:jwt-bearer"); * data["code"] = code; * data["grant_type"] = "authorization_code"; * * //var response = wb.UploadValues($"{IdpUrl}/api/openid_connect/token", "POST", data); * var response = wb.UploadValues($"{sams_endpoint_token}", "POST", data); * * var responseString = Encoding.ASCII.GetString(response); * dynamic tokenResponse = JObject.Parse(responseString); * * var token = handler.ReadToken((String)tokenResponse.id_token) as JwtSecurityToken; * var userId = token.Claims.First(c => c.Type == "sub").Value; * var userEmail = token.Claims.First(c => c.Type == "email").Value; * * TempData["id"] = userId; * TempData["email"] = userEmail; * //return RedirectToAction("Index", "HOME"); * return RedirectToAction("Index", "HOME"); * }*/ }