private string SignLoginTicketRequest(XmlNode?ticketRequest) { if (ticketRequest is null) { _logger.LogError("SignLoginTicketRequest: XmlLoginTicketRequest is null"); return(string.Empty); } string base64SignedCms; if (string.IsNullOrEmpty(CertificateFile)) { _logger.LogError("SignLoginTicketRequest: CertificatePath is null"); return(string.Empty); } try { _logger.LogInformation("SignLoginTicketRequest - Reading CertificateFile: {fileName}", CertificateFile); var securePassword = new NetworkCredential("", Password).SecurePassword; securePassword.MakeReadOnly(); var certSignatory = X509CertificateManager.GetCertificateFromFile(CertificateFile, securePassword); // Convierto el Login Ticket Request a bytes, firmo el msg y lo convierto a Base64 var msgEncoding = Encoding.UTF8; var msgBytes = msgEncoding.GetBytes(ticketRequest.OuterXml); var encodedSignedCms = X509CertificateManager.SignMessageBytes(msgBytes, certSignatory); base64SignedCms = Convert.ToBase64String(encodedSignedCms); } catch (Exception ex) { throw new Exception("SignLoginTicketRequest - Error signing LoginTicketRequest : " + ex.Message); } return(base64SignedCms); }
/// <summary> /// Initializes an authorization grant. /// </summary> /// <param name="statePrefix">Data to prefix OAuth state with to allow disambiguation between multiple concurrent authorization requests</param> /// <param name="codeChallengeAlgorithm">Code challenge algorithm method</param> public AuthorizationGrant(byte[] statePrefix, CodeChallengeAlgorithmType codeChallengeAlgorithm = CodeChallengeAlgorithmType.S256) { CodeChallengeAlgorithm = codeChallengeAlgorithm; var rng = new RNGCryptoServiceProvider(); var random = new byte[32]; try { // Calculate random state. rng.GetBytes(random); var state = new byte[statePrefix.LongLength + random.LongLength]; try { Array.Copy(statePrefix, 0, state, 0, statePrefix.LongLength); Array.Copy(random, 0, state, statePrefix.LongLength, random.LongLength); State = new NetworkCredential("", Base64UrlEncodeNoPadding(state)).SecurePassword; State.MakeReadOnly(); } finally { // Sanitize! for (long i = 0, n = state.LongLength; i < n; i++) { state[i] = 0; } } // Calculate code verifier. rng.GetBytes(random); CodeVerifier = new NetworkCredential("", Base64UrlEncodeNoPadding(random)).SecurePassword; CodeVerifier.MakeReadOnly(); } finally { // Sanitize! for (long i = 0, n = random.LongLength; i < n; i++) { random[i] = 0; } } }
private static uint GlobalUniqueID = 0; // OJO! NO ES THREAD-SAFE /// <summary> /// Construye un Login Ticket obtenido del WSAA /// </summary> /// <param name="service">Servicio al que se desea acceder</param> /// <param name="urlWsaa">URL del WSAA</param> /// <param name="x509CertificateFilePath">Ruta del certificado X509 (con clave privada) usado para firmar</param> /// <param name="password">Password del certificado X509 (con clave privada) usado para firmar</param> /// <param name="verbose">Nivel detallado de descripcion? true/false</param> /// <remarks></remarks> public async Task <WsaaTicket> LoginCmsAsync(string service, string x509CertificateFilePath, string password, bool verbose) { var ticketCacheFile = string.IsNullOrEmpty(TicketCacheFolderPath) ? service + "ticket.json" : TicketCacheFolderPath + service + "ticket.json"; if (File.Exists(ticketCacheFile)) { var ticketJson = File.ReadAllText(ticketCacheFile); var ticket = JsonConvert.DeserializeObject <WsaaTicket>(ticketJson); if (DateTime.UtcNow <= ticket.ExpirationTime) { return(ticket); } } const string ID_FNC = "[ObtenerLoginTicketResponse]"; CertificatePath = x509CertificateFilePath; VerboseMode = verbose; X509CertificateManager.VerboseMode = verbose; // PASO 1: Genero el Login Ticket Request try { GlobalUniqueID += 1; XmlLoginTicketRequest = new XmlDocument(); XmlLoginTicketRequest.LoadXml(XmlStrLoginTicketRequestTemplate); var xmlNodoUniqueId = XmlLoginTicketRequest.SelectSingleNode("//uniqueId"); var xmlNodoGenerationTime = XmlLoginTicketRequest.SelectSingleNode("//generationTime"); var xmlNodoExpirationTime = XmlLoginTicketRequest.SelectSingleNode("//expirationTime"); var xmlNodoService = XmlLoginTicketRequest.SelectSingleNode("//service"); xmlNodoGenerationTime.InnerText = DateTime.Now.AddMinutes(-10).ToString("s"); xmlNodoExpirationTime.InnerText = DateTime.Now.AddMinutes(+10).ToString("s"); xmlNodoUniqueId.InnerText = Convert.ToString(GlobalUniqueID); xmlNodoService.InnerText = service; Service = service; if (VerboseMode) { Console.WriteLine(XmlLoginTicketRequest.OuterXml); } } catch (Exception ex) { throw new Exception(ID_FNC + "***Error GENERANDO el LoginTicketRequest : " + ex.Message + ex.StackTrace); } string base64SignedCms; // PASO 2: Firmo el Login Ticket Request try { if (VerboseMode) { Console.WriteLine(ID_FNC + "***Leyendo certificado: {0}", CertificatePath); } var securePassword = new NetworkCredential("", password).SecurePassword; securePassword.MakeReadOnly(); var certFirmante = X509CertificateManager.GetCertificateFromFile(CertificatePath, securePassword); if (VerboseMode) { Console.WriteLine(ID_FNC + "***Firmando: "); Console.WriteLine(XmlLoginTicketRequest.OuterXml); } // Convierto el Login Ticket Request a bytes, firmo el msg y lo convierto a Base64 var msgEncoding = Encoding.UTF8; var msgBytes = msgEncoding.GetBytes(XmlLoginTicketRequest.OuterXml); var encodedSignedCms = X509CertificateManager.SignMessageBytes(msgBytes, certFirmante); base64SignedCms = Convert.ToBase64String(encodedSignedCms); } catch (Exception ex) { throw new Exception(ID_FNC + "***Error FIRMANDO el LoginTicketRequest : " + ex.Message); } string loginTicketResponse; // PASO 3: Invoco al WSAA para obtener el Login Ticket Response try { if (VerboseMode) { Console.WriteLine(ID_FNC + "***Llamando al WSAA en URL: {0}", IsProdEnvironment ? WsaaUrlProd : WsaaUrlHomologation); Console.WriteLine(ID_FNC + "***Argumento en el request:"); Console.WriteLine(base64SignedCms); } var wsaaService = new AfipLoginCmsServiceReference.LoginCMSClient(); wsaaService.Endpoint.Address = new EndpointAddress(IsProdEnvironment ? WsaaUrlProd : WsaaUrlHomologation); var response = await wsaaService.loginCmsAsync(base64SignedCms); loginTicketResponse = response.loginCmsReturn; if (VerboseMode) { Console.WriteLine(ID_FNC + "***LoguinTicketResponse: "); Console.WriteLine(loginTicketResponse); } } catch (Exception ex) { throw new Exception(ID_FNC + "***Error INVOCANDO al servicio WSAA : " + ex.Message); } // PASO 4: Analizo el Login Ticket Response recibido del WSAA try { XmlLoginTicketResponse = new XmlDocument(); XmlLoginTicketResponse.LoadXml(loginTicketResponse); UniqueId = uint.Parse(XmlLoginTicketResponse.SelectSingleNode("//uniqueId").InnerText); GenerationTime = DateTime.Parse(XmlLoginTicketResponse.SelectSingleNode("//generationTime").InnerText); ExpirationTime = DateTime.Parse(XmlLoginTicketResponse.SelectSingleNode("//expirationTime").InnerText); Sign = XmlLoginTicketResponse.SelectSingleNode("//sign").InnerText; Token = XmlLoginTicketResponse.SelectSingleNode("//token").InnerText; } catch (Exception ex) { throw new Exception(ID_FNC + "***Error ANALIZANDO el LoginTicketResponse : " + ex.Message); } var ticketResponse = new WsaaTicket { Sign = Sign, Token = Token, ExpirationTime = ExpirationTime }; File.WriteAllText(ticketCacheFile, JsonConvert.SerializeObject(ticketResponse)); return(ticketResponse); }