private TResponseType AuthenticatedRestRequest <TResponseType>(IRestRequest request) where TResponseType : LaunchKeyResponse, new() { request.AddParameter("app_key", this.appKey); var secretInfo = string.Format("{{\"secret\": '{0}', \"stamped\": '{1}'}}", this.secretKey, this.apiTime.Value.Add(DateTime.Now.Subtract(this.lastPing.Value)).ToString("yyyy-MM-dd HH:mm:ss")); var encryptionProvider = new LaunchKeyEncryptionProvider(); var encryptedSecretKey = encryptionProvider.Encrypt(this.apiPublicKey, Encoding.ASCII.GetBytes(secretInfo)); request.AddParameter("secret_key", Convert.ToBase64String(encryptedSecretKey)); request.AddParameter("signature", Convert.ToBase64String(encryptionProvider.Sign(this.appPrivateKey.Private, encryptedSecretKey))); return(this.RestRequest <TResponseType>(request)); }
/// <summary> /// Attempts to decode a deorbit request delivered via callback from the LaunchKey API. When a request is received, pass the request parameters to this method. If a user hash cannot be decoded for any reason, an exception will be thrown /// </summary> /// <param name="orbitData">The orbit data from the 'deorbit' GET parameter</param> /// <param name="signature">The signature which verifies the data in <paramref name="orbitData"/>, from the 'signature' GET parameter</param> /// <returns>The user hash being deorbited</returns> public string Deorbit(string orbitData, string signature) { var pingResponse = this.Ping(); if (!pingResponse.Successful) { throw new LaunchKeyApiException("Could not verify valid deorbit request, was unable ping API to get server time."); } var launchKeyEncryptionProvider = new LaunchKeyEncryptionProvider(); var signatureValid = launchKeyEncryptionProvider.VerifySignature( this.apiPublicKey, Encoding.ASCII.GetBytes(orbitData), Convert.FromBase64String(signature) ); // signature checks out if (signatureValid) { var jobj = JObject.Parse(orbitData); if (jobj.Property("launchkey_time") == null) { throw new LaunchKeyApiException("Invalid request parameters: launchkey_time was not present"); } if (jobj.Property("user_hash") == null) { throw new LaunchKeyApiException("Invalid request parameters: user_hash was not present"); } var requestLaunchKeyTime = (DateTime)jobj.Property("launchkey_time").Value; if (this.apiTime.Value.Subtract(requestLaunchKeyTime).TotalMinutes < 5.0) { return((string)jobj.Property("user_hash")); } else { throw new LaunchKeyApiException("Request is older than 5 minutes. Possible replay attack?"); } } else { throw new LaunchKeyApiException("Signature validation failed!"); } }
/// <summary> /// Poll the status of an authentication request using the reference id supplied in <paramref name="authRequest"/>. Implicitly calls Ping(). /// </summary> /// <param name="authRequest">unique authentication request reference ID to check</param> /// <returns><see cref="PollResponse"/> object including status of request</returns> public PollResponse Poll(string authRequest) { if (string.IsNullOrWhiteSpace(authRequest)) { throw new ArgumentException("authRequest must be provided"); } this.EnsureAuthorizationRecent(); RestRequest request = new RestRequest("poll", Method.GET); request.AddParameter("auth_request", authRequest); request.AddParameter("SUPPRESS_RESPONSE_CODES", "TRUE"); var response = this.AuthenticatedRestRequest <PollResponse>(request); if (response.Auth != null) { var encryptionProvider = new LaunchKeyEncryptionProvider(); var authPayload = Convert.FromBase64String(response.Auth.Replace("\\/", "/")); var decryptedPayload = encryptionProvider.Decrypt(this.appPrivateKey.Private, authPayload); var decryptedText = Encoding.ASCII.GetString(decryptedPayload); var jobj = JObject.Parse(decryptedText); response.DecryptedAuth = new DecryptedPollResponse() { AuthRequest = jobj.Property("auth_request") != null?jobj.Property("auth_request").Value.ToString() : null, DeviceId = jobj.Property("device_id") != null?jobj.Property("device_id").Value.ToString() : null, AppPins = jobj.Property("app_pins") != null?jobj.Property("app_pins").Value.ToString().Split(',') : null, Response = jobj.Property("response") != null?bool.Parse(jobj.Property("response").Value.ToString()) : false }; } return(response); }