">mixi Developer Center (mDC)

mixi Apps

mixi Apps (English) » Technical Specification » PC » Work with External Servers

Work with External Servers

A mixi App can be a social application by making use of the Person & Friends API, also, mashup with content provided by other web services throughout the Internet adds much more value on the mixi App. In some OpenSocial applications that have already been popular overseas, certain external web services/content are called and provided through the applications. Not only can the external content is provided, the developer is able to explore new user experience by associating the external services with the social graphs in the mixi App.

makerequest1

The feature for communicating from the application to the external servers is defined as the Gadgets Core JavaScript API in OpenSocial. The gadgets.io.makeRequest() is available to communicate the application to the external servers. The developer is able to use this makeRequest() to acquire content from the external servers in the mixi App.

Features of the makeRequest()

The makeRequest() provides several functionalities that are powerful, yet the usage is rather simple. The makeRequest() has following characteristics:.

  • Most of the methods (including GET and POST) are supported as HTTP methods.
  • Some of the standard formats of content acquired from the external servers are supported. Other formats are converted to the one easily handled by JavaScript.
  • Security-related specifications including signatures are incorporated to communicate safely with the external servers.

The following parameters can be specified for the makeRequest():

  • URL indicating the location of content to be obtained
  • Callback function to be called when the result is returned
  • Parameters related to requests to the external servers

Parameters that can be specified are defined in the gadgets.io.RequestParameters class. The developer is able to customize requests to the external servers by utilizing these parameters.

gadgets.io.AUTHORIZATION

The access to the external servers by the makeRequest() can be secured by signatures. which can be specified by the AUTHORIZATION parameter.

  • gadgets.io.AuthorizationType.NONE – without signature
  • gadgets.io.AuthorizationType.SIGNED – with signature

* Requests for approval authorization by OAuth is not currently supported.

gadgets.io.CONTENT_TYPE

With the CONTENT_TYPE parameter, an expected format for content obtained from the external server can be specified. With this parameter, the content is automatically converted to a JavaScript object and thus the content can be easily handled by a mixi App.

  • gadgets.io.ContentType.DOM – Expect result in XML format
  • gadgets.io.ContentType.FEED – Expect result in RSS or ATOM Feed format
  • gadgets.io.ContentType.JSON – Expect result in JSON character string format
  • gadgets.io.ContentType.TEXT – Expect result in text format

In addition, an HTTP method can be supported by the METHOD parameter and information to be transmitted at POST can be specified by the POST_DATA parameter.

When the callback function specified by the second argument of the makeRequest()is called,.an object containing the result is passed to the function. The object contains the following properties.

  • data – contains the results properly converted according to the type of content specified when making a request
  • rc – contains HTTP status code, which is the result of making a request
  • errors – contains error message in an array if any error is returned as the result of making a request
  • text – contains the string of content obtained as the result of making a request

The developer is able to use the content obtained from the external servers based on these properties.

Sample Code

The following code is an example for acquiring feed documents from an external server and processing the result.

var url = "http://your.server.host/recent";
var params = {};
params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.POST;
params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.FEED;
var post_data = {span : 7};
params[gadgets.io.RequestParameters.POST_DATA] = gadgets.io.encodeValues(post_data);
params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.NONE;
gadgets.io.makeRequest(url, function(response) {
  var feed = response.data;
  var title = feed.Title;
  var link = feed.Link;
  // do something...
  var entries = feed.Entry;
  for (var i = 0; i < entries.length; i++) {
    var entry = entries[i];
    var entryTitle = entry.Title;
    var entryLink = entry.Link;
    // do something...
  }
}, params);

Access Restrictions

The following restrictions are applied to the gadgets.io.makeRequest() for efficient resource allocation for whole mixi Platform in terms of traffic from mixi Apps (PC version) to the external servers.

  • In the case that times out (10 seconds) to a host site occurs 20 times consecutively, another connection to the host cannot be generated for next 15 seconds.
  • For the connection attempt by makeRequest() within the 15 seconds, a response including error code 504 is returned (same as normal timeout).

Each of the parameters above may be changed without prior notice depending on the operation status of the mixi Platform in mixi’s sole discretion.

Request with Signature

When the mixi App communicates with the external servers by the makeRequest() , such external server should validate the request from the mixi App. By verifying the followings, the external server can be secured by denying illegal accesses:

  • Request must be sent from the mixi Platform.
  • Request is not tampered.

In order to make a request with signature, ”SIGNED” can be specified for the AUTHORIZATION parameter.

The list below illustrates an example of processing for making signed requests.

var url = "http://your.server.host/recent";
var params = {};
params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.SIGNED;
gadgets.io.makeRequest(url, function(response) {
  // do something...
}, params);

The following values can be added as parameters for the signed request originated in a mixi App to the external servers:

  • oauth_consumer_key – “mixi.jp”
  • oauth_signature_method – “RSA-SHA1″

From the external host point of view, the request can be validated based on each parameter value, signature given as the oauth_signature parameter value, and public key.

Public Key

-----BEGIN CERTIFICATE-----
MIIDNzCCAh+gAwIBAgIJAOwgl6RQpug2MA0GCSqGSIb3DQEBBQUAMDIxCzAJBgNV
BAYTAkpQMREwDwYDVQQKDAhtaXhpIEluYzEQMA4GA1UEAwwHbWl4aS5qcDAeFw0x
MzExMDcwODQxMTFaFw0yMzExMDUwODQxMTFaMDIxCzAJBgNVBAYTAkpQMREwDwYD
VQQKDAhtaXhpIEluYzEQMA4GA1UEAwwHbWl4aS5qcDCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAK2ojofjDNhiD6rDFUv4k728rGeLDf6VERU4RsdHBkvS
UZhx7SiRidhAHQ7QX6DP9W8ALeM6i2s+vxmfYbL9NrsKx/HxWZvuxmV4ELgRsDRN
0LUjEJv+hyI/nFfPlHmvYgKx501fTWn9DbBUxaKTbA2984Styrlf8etSRkkdx+Ua
742iDEXTH6jtxFSmcPvcvAXbdoUNNx95d+3QNoG8p0zaSMUwXGn7jCVcz+WhDkCO
n2ajknn539YXVRp6I4DjJ+8M1ZmC1FTcb5PsVGUuxCxhwZc6LDq/qMxJCi20AzD9
McYsyZS1LB+q/dwibaLEZbIh+fGkUaRoRRhrOFNJ0dMCAwEAAaNQME4wHQYDVR0O
BBYEFLWrc309hb0KbH56w0aseZPQHWc2MB8GA1UdIwQYMBaAFLWrc309hb0KbH56
w0aseZPQHWc2MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAGh27dw2
C1pxpDiA3X5zzrRDuBuCRXyY1Ywq3FboTVsUrc2NfOCOm27674D/tZtANxUBrs3k
JI1hY6mbQgvTaXNm6wuxknyQWeaKkdacdtbKeIdtut4APeY/K9NGLHqBjglpx+JK
jpXBVwVGqH36q9qqxZvCk/LZGzVuoYIsfolIUVKfQwpybc2TptdDH3Nuu/EXz/BK
xpkjcpasg+apX4zifOkdVoEmsjO1K1UeSvHDugEZRCLg/Bkbh9tK47waVj4BYvro
JkIkQk47Ws2bAlth3YaNAgjLibzyjCT/5YTJujWZHuMG/zpZMoYLuk7oJP4f4DKH
aw6UQsWgwzyYhnM=
-----END CERTIFICATE-----

Verification of Signed requests

The following explains how to validate the requests with signatures. If you do not know what signed requests are or why you must use them, please check the signed requests introduction page.

* The explanation below is a partially modified translation of “Validating Signed Requests”:

http://wiki.opensocial.org/index.php?title=Validating_Signed_Requests

Obtaining Encryption Keys

Signed requests currently include three parameters:

  • oauth_consumer_key
  • xoauth_signature_publickey
  • oauth_signature_method

The oauth_consumer_key parameter indicates the container from which the request is being sent. The oauth_signature_method parameter indicates the method used to sign the request. For requests signed with RSA-SHA1, the xoauth_signature_publickey parameter contains the name of the public key used to sign the request.

For HMAC-SHA1, you will need to establish a secret key between your application and the container. Each container has a different mechanism for doing so — please consult your target container’s documentation for information about establishing a shared secret key.

For RSA-SHA1, you will need to obtain the certificate referenced by xoauth_signature_publickey. For your convenience, there is a list of public keys for each container available at https://opensocialresources.appspot.com/certificates/ along with links to each certificate. This site is for convenience only and not approved by the containers listed! For the best security, be sure to check your container’s documentation to verify the location of the appropriate public key!

Certificates should not be fetched each time you want to validate parameters — instead, implement a server side key cache indexed on the value of xoauth_signature_publickey, oauth_consumer_key, and oauth_signature_method. If these values change, you will need to pull a new certificate down and store it in your key cache.

OAuth Signing Mechanism

Parameter signature is implemented according to the OAuth parameter signature specification.

Check the following page for information about generating the Signature Base String:

http://oauth.net/core/1.0/#rfc.section.A.5.1

PHP

Client Side Code

Your client code should make a request in the following manner. We will be specifying a gadgets.io.AuthorizationType.SIGNED request, and will expect the response to be returned as JSON.

function makeSignedRequest() {
  var params = {};
  params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.SIGNED;
  params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
  var url = "http://graargh.returnstrue.com/buh/fetchme.php";
  gadgets.io.makeRequest(url, response, params);
};

function response(ret) {
  output(ret.data);

  var html = [ ret.data.validated, "<br />",
    "oauth_consumer_key: ", ret.data.query.oauth_consumer_key, "<br />",
    "oauth_nonce: ", ret.data.query.oauth_nonce, "<br />",
    "oauth_signature: ", ret.data.query.oauth_signature, "<br />",
    "oauth_signature_method: ", ret.data.query.oauth_signature_method, "<br />",
    "oauth_timestamp: ", ret.data.query.oauth_timestamp, "<br />",
    "oauth_token: ", ret.data.query.oauth_token, "<br />",
    "opensocial_app_id: ", ret.data.query.opensocial_app_id, "<br />",
    "opensocial_owner_id: ", ret.data.query.opensocial_owner_id, "<br />",
    "xoauth_signature_publickey: ", ret.data.query.xoauth_signature_publickey
].join("");

  output(html);
};

makeSignedRequest();

Server Side Code

The following code shows the server side code for fetchme.php. This code relies on OAuth.php (revision 526) from the open source OAuth library project.

http://code.google.com/p/oauth/
http://oauth.googlecode.com/svn-history/r526/code/php/OAuth.php

The code implements these steps:

  • Creates an MixiSignatureMethod class that extends OAuthSignatureMethod_RSA_SHA1
  • Creates an OAuthRequest object from the current request
  • Creates an instance of MixiSignatureMethod
  • Checks the request using the MixiSignatureMethod class
  • Outputs a JSON object

This example is not meant to be production quality code — merely a demonstration of the steps you would take to validate a signed request server-side.

require_once("OAuth.php");

class MixiSignatureMethod extends OAuthSignatureMethod_RSA_SHA1 {
  protected function fetch_public_cert(&$request) {
  return << EOD
-----BEGIN CERTIFICATE-----
MIIDNzCCAh+gAwIBAgIJAOwgl6RQpug2MA0GCSqGSIb3DQEBBQUAMDIxCzAJBgNV
BAYTAkpQMREwDwYDVQQKDAhtaXhpIEluYzEQMA4GA1UEAwwHbWl4aS5qcDAeFw0x
MzExMDcwODQxMTFaFw0yMzExMDUwODQxMTFaMDIxCzAJBgNVBAYTAkpQMREwDwYD
VQQKDAhtaXhpIEluYzEQMA4GA1UEAwwHbWl4aS5qcDCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAK2ojofjDNhiD6rDFUv4k728rGeLDf6VERU4RsdHBkvS
UZhx7SiRidhAHQ7QX6DP9W8ALeM6i2s+vxmfYbL9NrsKx/HxWZvuxmV4ELgRsDRN
0LUjEJv+hyI/nFfPlHmvYgKx501fTWn9DbBUxaKTbA2984Styrlf8etSRkkdx+Ua
742iDEXTH6jtxFSmcPvcvAXbdoUNNx95d+3QNoG8p0zaSMUwXGn7jCVcz+WhDkCO
n2ajknn539YXVRp6I4DjJ+8M1ZmC1FTcb5PsVGUuxCxhwZc6LDq/qMxJCi20AzD9
McYsyZS1LB+q/dwibaLEZbIh+fGkUaRoRRhrOFNJ0dMCAwEAAaNQME4wHQYDVR0O
BBYEFLWrc309hb0KbH56w0aseZPQHWc2MB8GA1UdIwQYMBaAFLWrc309hb0KbH56
w0aseZPQHWc2MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAGh27dw2
C1pxpDiA3X5zzrRDuBuCRXyY1Ywq3FboTVsUrc2NfOCOm27674D/tZtANxUBrs3k
JI1hY6mbQgvTaXNm6wuxknyQWeaKkdacdtbKeIdtut4APeY/K9NGLHqBjglpx+JK
jpXBVwVGqH36q9qqxZvCk/LZGzVuoYIsfolIUVKfQwpybc2TptdDH3Nuu/EXz/BK
xpkjcpasg+apX4zifOkdVoEmsjO1K1UeSvHDugEZRCLg/Bkbh9tK47waVj4BYvro
JkIkQk47Ws2bAlth3YaNAgjLibzyjCT/5YTJujWZHuMG/zpZMoYLuk7oJP4f4DKH
aw6UQsWgwzyYhnM=
-----END CERTIFICATE-----
EOD;
  }
}

//Build a request object from the current request
$request = OAuthRequest::from_request(null, null, array_merge($_GET, $_POST));

//Initialize the new signature method
$signature_method = new MixiSignatureMethod();

//Check the request signature
@$signature_valid = $signature_method->check_signature($request, null, null, $_GET["oauth_signature"]);

//Build the output object
$payload = array();
if ($signature_valid == true) {
  $payload["validated"] = "Success! The data was validated";
} else {
  $payload["validated"] = "This request was spoofed";
}

//Add extra parameters to help debugging
$payload["query"] = array_merge($_GET, $_POST);
$payload["rawpost"] = file_get_contents("php://input");

//Return the response as JSON
print(json_encode($payload));

Results

When you run the client side script against the server code, the “response” function will be called, with one of the following objects:

If the request was validated:

{ "validated" : "Success! The data was validated",
  "query" : {  }
}

If the request was not validated:

{ "validated" : "This request was spoofed",
  "query" : {  }
}

Response prints this out in the following format:

Java

Client Side Code

var servletUrl="http://oauthtest.s42.eatj.com/oauth/SignedFetchVerifyServlet";
function response(data) {
  document.getElementById('dom_handle').innerHTML=data.text;
};
function request() {
  var params={};
  params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.SIGNED;
  gadgets.io.makeRequest(servletUrl,response,params);
};
gadgets.util.registerOnLoadHandler(request);

Server Side Code

The code implements these steps:

  • Create an OAuthServiceProvider
  • Create an OAuthConsumer and populate the RSA Certificate with mixi’s Certificate
  • Extract the OAuthMessage from the HttpServletRequest
  • Create an OAuthAccessor using the consumer
  • Checks the OAuthMessage using this accessor

This code relies on Java OAuth from the open source Opensocial Java Client.

http://code.google.com/p/oauth/

This example is not meant to be production quality code — merely a demonstration of the steps you would take to validate a signed request server-side.

package net.oauth.example.provider.servlets;

import net.oauth.OAuth;
import net.oauth.OAuthAccessor;
import net.oauth.OAuthConsumer;
import net.oauth.OAuthMessage;
import net.oauth.OAuthProblemException;
import net.oauth.OAuthServiceProvider;
import net.oauth.server.OAuthServlet;
import net.oauth.signature.RSA_SHA1;

import java.util.ArrayList;
import java.io.IOException;
import java.util.Map;
import java.io.PrintWriter;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SignedFetchVerifyServlet extends HttpServlet {

  private final static String CERTIFICATE =
    "-----BEGIN CERTIFICATE-----\n"
    + "MIIDNzCCAh+gAwIBAgIJAOwgl6RQpug2MA0GCSqGSIb3DQEBBQUAMDIxCzAJBgNV\n"
    + "BAYTAkpQMREwDwYDVQQKDAhtaXhpIEluYzEQMA4GA1UEAwwHbWl4aS5qcDAeFw0x\n"
    + "MzExMDcwODQxMTFaFw0yMzExMDUwODQxMTFaMDIxCzAJBgNVBAYTAkpQMREwDwYD\n"
    + "VQQKDAhtaXhpIEluYzEQMA4GA1UEAwwHbWl4aS5qcDCCASIwDQYJKoZIhvcNAQEB\n"
    + "BQADggEPADCCAQoCggEBAK2ojofjDNhiD6rDFUv4k728rGeLDf6VERU4RsdHBkvS\n"
    + "UZhx7SiRidhAHQ7QX6DP9W8ALeM6i2s+vxmfYbL9NrsKx/HxWZvuxmV4ELgRsDRN\n"
    + "0LUjEJv+hyI/nFfPlHmvYgKx501fTWn9DbBUxaKTbA2984Styrlf8etSRkkdx+Ua\n"
    + "742iDEXTH6jtxFSmcPvcvAXbdoUNNx95d+3QNoG8p0zaSMUwXGn7jCVcz+WhDkCO\n"
    + "n2ajknn539YXVRp6I4DjJ+8M1ZmC1FTcb5PsVGUuxCxhwZc6LDq/qMxJCi20AzD9\n"
    + "McYsyZS1LB+q/dwibaLEZbIh+fGkUaRoRRhrOFNJ0dMCAwEAAaNQME4wHQYDVR0O\n"
    + "BBYEFLWrc309hb0KbH56w0aseZPQHWc2MB8GA1UdIwQYMBaAFLWrc309hb0KbH56\n"
    + "w0aseZPQHWc2MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAGh27dw2\n"
    + "C1pxpDiA3X5zzrRDuBuCRXyY1Ywq3FboTVsUrc2NfOCOm27674D/tZtANxUBrs3k\n"
    + "JI1hY6mbQgvTaXNm6wuxknyQWeaKkdacdtbKeIdtut4APeY/K9NGLHqBjglpx+JK\n"
    + "jpXBVwVGqH36q9qqxZvCk/LZGzVuoYIsfolIUVKfQwpybc2TptdDH3Nuu/EXz/BK\n"
    + "xpkjcpasg+apX4zifOkdVoEmsjO1K1UeSvHDugEZRCLg/Bkbh9tK47waVj4BYvro\n"
    + "JkIkQk47Ws2bAlth3YaNAgjLibzyjCT/5YTJujWZHuMG/zpZMoYLuk7oJP4f4DKH\n"
    + "aw6UQsWgwzyYhnM=\n"
    + "-----END CERTIFICATE-----";

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                           throws ServletException, IOException {
    verifyFetch(req, resp);
  }

  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp)
                            throws ServletException, IOException {
    verifyFetch(req, resp);
  }

  private void verifyFetch(HttpServletRequest request, HttpServletResponse resp)
                                    throws IOException, ServletException {
    resp.setContentType("text/html; charset=UTF-8");
    PrintWriter out = resp.getWriter();

    try {
      OAuthServiceProvider provider = new OAuthServiceProvider(null, null, null);
      OAuthConsumer consumer = new OAuthConsumer(null, "mixi.jp", null, provider);
      consumer.setProperty(RSA_SHA1.X509_CERTIFICATE, CERTIFICATE);

      String method = request.getMethod();
      String requestUrl = getRequestUrl(request);
      List requestParameters = getRequestParameters(request);

      OAuthMessage message = new OAuthMessage(method, requestUrl, requestParameters);

      OAuthAccessor accessor = new OAuthAccessor(consumer);
      out.print("*** OAuthMessage Params:");
      out.print("URL: " + OAuthServlet.htmlEncode(message.URL));
      for (java.util.Map.Entry param : message.getParameters()) {
        String key = param.getKey().toString();
        String value = param.getValue().toString();
        out.print("");
        out.print("Param Name-->" + OAuthServlet.htmlEncode(key));
        out.print(" ");
        out.print("Value-->" + OAuthServlet.htmlEncode(value));
      }
      out.print("");
      out.print(" VALIDATING SIGNATURE ");
      out.print("");
      message.validateSignature(accessor);
      out.print("REQUEST STATUS::OK");
      out.print("");
    } catch (OAuthProblemException ope) {
      out.print("");
      out.print("OAuthProblemException-->" + OAuthServlet.htmlEncode(ope.getProblem()));
    } catch (Exception e) {
      out.println(e);
      System.out.println(e);
      throw new ServletException(e);
    } finally {
      out.flush();
    }
  }

  /**
   * Constructs and returns the full URL associated with the passed request
   * object.
   *
   * @param  request Servlet request object with methods for retrieving the
   *         various components of the request URL
   */
  public static String getRequestUrl(HttpServletRequest request) {
    StringBuilder requestUrl = new StringBuilder();
    String scheme = request.getScheme();
    int port = request.getLocalPort();

    requestUrl.append(scheme);
    requestUrl.append("://");
    requestUrl.append(request.getServerName());

    if ((scheme.equals("http") && port != 80)
|| (scheme.equals("https") && port != 443)) {
      requestUrl.append(":");
      requestUrl.append(port);
    }

    requestUrl.append(request.getContextPath());
    requestUrl.append(request.getServletPath());

    return requestUrl.toString();
  }

  /**
   * Constructs and returns a List of OAuth.Parameter objects, one per
   * parameter in the passed request.
   *
   * @param  request Servlet request object with methods for retrieving the
   *         full set of parameters passed with the request
   */
  public static List getRequestParameters(HttpServletRequest request) {

    List parameters = new ArrayList();

    for (Object e : request.getParameterMap().entrySet()) {
      Map.Entry entry = (Map.Entry) e;

      for (String value : entry.getValue()) {
        parameters.add(new OAuth.Parameter(entry.getKey(), value));
      }
    }

    return parameters;
  }
}

Results

When you run the client side script against the server code, and if the request was validated:

*** OAuthMessage Params:
URL: http://oauthtest.s42.eatj.com/oauth/SignedFetchVerifyServlet
Param Name-->oauth_consumer_key Value-->mixi.jp
Param Name-->oauth_nonce Value-->7fe2ce6b24e17c86
Param Name-->opensocial_app_id Value-->10449685582340194994
Param Name-->opensocial_viewer_id Value-->xxxxxxxx
Param Name-->oauth_timestamp Value-->1211519778
Param Name-->opensocial_owner_id Value-->xxxxxxxx
Param Name-->oauth_signature Value-->eYwX2yWLpOZ+gb5oEFeIy+EM3j237nrj/1rj3yp69jgo
/QaPk/OnXbXP9imEcERxtQLj9QqDD8cjbjMJ46VINc7b
Lab8qER1Xhkf4tTIkwfFXJW9tjQMBuGO8OVf9v0UAjAr
uWfSN331LLgGFecKQR5UTD0qAAyzTnFY9aSmqg8=
Param Name-->xoauth_signature_publickey Value-->pub.1199819524.-1556113204990931254.cer
Param Name-->oauth_token Value-->
Param Name-->oauth_signature_method Value-->RSA-SHA1
VALIDATING SIGNATURE
REQUEST STATUS::OK

C#

Server side code

This code relies on the csharp OAuth library from the open source OAuth library project.

http://code.google.com/p/oauth/

This example is not meant to be production quality code — merely a demonstration of the steps you would take to validate a signed request server-side.

// -----------------------------------------------------------------------------------
//
//  OBasePage.cs to validate oAuth signature - .NET
//  by XtremeHeights
//  Last Modification: 4th Oct 2008
//
//  For more information, visit:
//  http:/www.xtremeheights.com/
//  email: contact@xtremeheights.com
//
//
//  Thanks:
//  Khushal Patel for creating plug & plug code for implementing oAuth in .NET
//  Nemesh Singh for fixing the code which started spoofing every request after 25th sep 2008
//
// -----------------------------------------------------------------------------------

using System;
using System.Collections;
using System.Configuration;
using System.Web;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Collections.Specialized;
using OAuth;

public class oBasePage : System.Web.UI.Page
{
  HttpContext htp;
  public oBasePage(HttpContext _htp)
  {
    htp = _htp;
  }

  public bool isvalidrequest()
  {
    //If you want to import certificate file directly then uncomment the below line and comment the certificate
    //X509Certificate Cert = X509Certificate.CreateFromCertFile(htp.Request.PhysicalApplicationPath + "/bin/pub.1199819524.-1556113204990931254.cer");

    X509Certificate2 cert = new X509Certificate2();
    cert.Import(Encoding.ASCII.GetBytes(
@"-----BEGIN CERTIFICATE-----
MIIDNzCCAh+gAwIBAgIJAOwgl6RQpug2MA0GCSqGSIb3DQEBBQUAMDIxCzAJBgNV
BAYTAkpQMREwDwYDVQQKDAhtaXhpIEluYzEQMA4GA1UEAwwHbWl4aS5qcDAeFw0x
MzExMDcwODQxMTFaFw0yMzExMDUwODQxMTFaMDIxCzAJBgNVBAYTAkpQMREwDwYD
VQQKDAhtaXhpIEluYzEQMA4GA1UEAwwHbWl4aS5qcDCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAK2ojofjDNhiD6rDFUv4k728rGeLDf6VERU4RsdHBkvS
UZhx7SiRidhAHQ7QX6DP9W8ALeM6i2s+vxmfYbL9NrsKx/HxWZvuxmV4ELgRsDRN
0LUjEJv+hyI/nFfPlHmvYgKx501fTWn9DbBUxaKTbA2984Styrlf8etSRkkdx+Ua
742iDEXTH6jtxFSmcPvcvAXbdoUNNx95d+3QNoG8p0zaSMUwXGn7jCVcz+WhDkCO
n2ajknn539YXVRp6I4DjJ+8M1ZmC1FTcb5PsVGUuxCxhwZc6LDq/qMxJCi20AzD9
McYsyZS1LB+q/dwibaLEZbIh+fGkUaRoRRhrOFNJ0dMCAwEAAaNQME4wHQYDVR0O
BBYEFLWrc309hb0KbH56w0aseZPQHWc2MB8GA1UdIwQYMBaAFLWrc309hb0KbH56
w0aseZPQHWc2MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAGh27dw2
C1pxpDiA3X5zzrRDuBuCRXyY1Ywq3FboTVsUrc2NfOCOm27674D/tZtANxUBrs3k
JI1hY6mbQgvTaXNm6wuxknyQWeaKkdacdtbKeIdtut4APeY/K9NGLHqBjglpx+JK
jpXBVwVGqH36q9qqxZvCk/LZGzVuoYIsfolIUVKfQwpybc2TptdDH3Nuu/EXz/BK
xpkjcpasg+apX4zifOkdVoEmsjO1K1UeSvHDugEZRCLg/Bkbh9tK47waVj4BYvro
JkIkQk47Ws2bAlth3YaNAgjLibzyjCT/5YTJujWZHuMG/zpZMoYLuk7oJP4f4DKH
aw6UQsWgwzyYhnM=
-----END CERTIFICATE-----"));

    //Getting Post variables
    string http_params;
    NameValueCollection _p = htp.Request.Form;
    Hashtable _hp = new Hashtable();

    foreach (string k in _p.Keys)
    {
      if (k != null)
      {
        _hp[k] = _p[k];
      }
    }

    SortedList _ps = new SortedList((IDictionary)_hp);

    string[] pairs1 = new string[_ps.Keys.Count];
    int l = 0;

    foreach (string name in _ps.Keys)
    {
      pairs1[l++] = name + "=" + Uri.EscapeDataString(_ps[name].ToString());
    }
    http_params = (String.Join("&", pairs1));

    if (_ps.Keys.Count != 0)
    {
      http_params = "&" + http_params;
    }

    /* RSACryptoServiceProvider Provider = CertUtil.GetCertPublicKey(Cert); // if importing the file directly... */
    RSACryptoServiceProvider Provider = (RSACryptoServiceProvider)cert.PublicKey.Key;
    OAuth.OAuthBase ba = new OAuthBase();

    string signature = (htp.Request.QueryString["oauth_signature"]);

    string baseString = ba.GenerateSignatureBase(htp.Request.Url,
      htp.Request.QueryString["oauth_consumer_key"],
      "",
      htp.Request.QueryString["oauth_token"],
      "",
      htp.Request.HttpMethod,
      htp.Request.QueryString["oauth_timestamp"],
      htp.Request.QueryString["oauth_nonce"],
      "RSA-SHA1",
      http_params);

    byte[] sign = Convert.FromBase64String(signature);
    byte[] bstring = Encoding.UTF8.GetBytes(baseString);
    htp.Response.Write(htp.Request.QueryString["oauth_token"]);

    return (Provider.VerifyData(bstring, "SHA1", sign));
  }
}

If you have any comments or questions about this page, please discuss them in the OpenSocial developer forum.

http://groups.google.com/group/opensocial-api/topics

TOP OF THIS PAGE