public static CanvasRequest VerifyAndDecode(IAuthenticatedWho authenticatedWho, String input, String secret)
        {
            CanvasRequest canvasRequest           = null;
            DataContractJsonSerializer serializer = null;

            String[] split           = null;
            String   encodedSig      = null;
            String   encodedEnvelope = null;
            String   decodedEnvelope = null;
            Type     type            = null;

            // Get the signature and envelope
            split           = GetParts(authenticatedWho, input);
            encodedSig      = split[0];
            encodedEnvelope = split[1];

            // Verify the encoding and envelope
            Verify(authenticatedWho, secret, encodedEnvelope, encodedSig);

            // Create a new type for our json serializer
            type = typeof(CanvasRequest);

            // Create a new serializer using the canvas request type
            serializer = new DataContractJsonSerializer(type);

            Byte[] b = Convert.FromBase64String(encodedEnvelope);
            decodedEnvelope = Encoding.Default.GetString(b);

            // Create the canvas request object from the encoded json body
            canvasRequest = serializer.ReadObject(new MemoryStream(Encoding.Unicode.GetBytes(decodedEnvelope))) as CanvasRequest;

            // Return the request as a Canvas Object
            return(canvasRequest);
        }
        public HttpResponseMessage Canvas(String tenantId, String flowId, String playerUrl)
        {
            String              redirectUrl   = null;
            String              signedRequest = null;
            CanvasRequest       canvasRequest = null;
            HttpResponseMessage response      = null;

            try
            {
                // Get the signed request from the form post
                signedRequest = System.Web.HttpContext.Current.Request.Form["signed_request"];

                // Grab the canvas request object from the post
                // The secret needs to be stored somewhere - actually, it doesn't - we don't need the secret at all
                canvasRequest = SalesforceCanvasUtils.VerifyAndDecode(null, signedRequest, "6156156167154975556");

                if (flowId == null ||
                    flowId.Trim().Length == 0)
                {
                    throw new ArgumentNullException("BadRequest", "A flow identifier is required.  Please pass in a parameter for \"flow-id\".");
                }

                if (tenantId == null ||
                    tenantId.Trim().Length == 0)
                {
                    throw new ArgumentNullException("BadRequest", "A tenant identifier is required.  Please pass in a parameter for \"tenant-id\".");
                }

                if (playerUrl == null ||
                    playerUrl.Trim().Length == 0)
                {
                    throw new ArgumentNullException("BadRequest", "A player is required.  Please pass in a parameter for \"player-url\".");
                }

                // Construct the redirect url so the player knows what to do
                redirectUrl  = "";
                redirectUrl += SettingUtils.GetStringSetting(SETTING_SERVER_BASE_PATH) + "/" + tenantId + "/play/" + playerUrl;
                redirectUrl += "?session-token=" + canvasRequest.client.oauthToken;
                redirectUrl += "&session-url=" + HttpUtility.HtmlEncode(canvasRequest.client.instanceUrl + canvasRequest.context.links.partnerUrl);

                // Create the run url stuff using utils
                redirectUrl = RunUtils.CompleteRunUrl(redirectUrl, Guid.Parse(flowId));

                // Tell the caller to redirect back to the desired location
                response = Request.CreateResponse(HttpStatusCode.RedirectMethod, redirectUrl);
                response.Headers.Add("Location", redirectUrl);
            }
            catch (Exception exception)
            {
                throw BaseHttpUtils.GetWebException(HttpStatusCode.BadRequest, BaseHttpUtils.GetExceptionMessage(exception));
            }

            return(response);
        }