I'm attempting to authenticate against Magento's OAuth system for the purpose of customer mobile login - there are lots of examples for php but I can only find bits and pieces for C#. If possible, I'd like to circumvent use of a browser and perform the login programmatically.
Authentication and use of the REST API is contained within a PCL library - compatible with .NET 4.5, Xamarin.IOS, Xamarin.Android and Windows Phone Silverlight. As a result, I'm having to use portable libraries such as RestSharp.Portable.
So far, I've been able to retrieve the unauthorised tokens; oauth_token and oauth_token_secret through the use of /oauth/initiate but I can't work out the next two steps /oauth/authorize and /oauth/token. The official Magento guide (http://www.magentocommerce.com/api/rest/authentication/oauth_authentication.html) suggests the next action is to visit /oauth/authorize, allow the user to sign in and then recover two url parameters from the callback url. However, when I attempt this in a browser, it simply redirects me to /index.php/customer/account/login/ - I'm expecting it to redirect to my callback url (localhost) so that I can detect the redirection through the use of the location cookie and then retrieve the tokens that way.
Can anybody advise on how to complete the authorization?
var magento = new MagentoHelper();
await magento.OAuthInitiate();
await magento.OAuthAuthorize();
await magento.OAuthToken();
public class MagentoHelper
{
public readonly string ServiceUrl = ""; // e.g. http://127.0.0.1
public readonly string MagentoService = ""; // e.g. /magento
public readonly string ConsumerKey = "";
public readonly string ConsumerSecret = "";
public readonly string CustomerUsername = "";
public readonly string CustomerPassword = "";
private RestClient _client;
private MagentoTools _magentoTools;
private string _oauthToken;
private string _oauthTokenSecret;
public MagentoHelper()
{
_client = new RestClient(ServiceUrl);
_magentoTools = new MagentoTools();
}
/// <summary>
/// Retrieve unauthorized tokens from OAuth service
/// </summary>
public async Task OAuthInitiate()
{
var request = new RestRequest(MagentoService + "/oauth/initiate", HttpMethod.Post);
string nonce = _magentoTools.GetNonce();
string timestamp = _magentoTools.GetTimestamp();
var parameters = new Dictionary<string, string>();
parameters.Add("oauth_callback", "http://localhost:8888");
parameters.Add("oauth_consumer_key", ConsumerKey);
parameters.Add("oauth_nonce", nonce);
parameters.Add("oauth_signature_method", "HMAC-SHA1");
parameters.Add("oauth_timestamp", timestamp);
parameters.Add("oauth_version", "1.0");
var postUrl = new Uri(ServiceUrl + MagentoService + "/oauth/initiate");
var signature = OAuth1.GetSignature("POST", postUrl, parameters, ConsumerSecret, "").ToString();
parameters.Add("oauth_signature", OAuth1.EncodeString(signature));
string authHeader = _magentoTools.GetAuthorizationHeader(parameters.ToList());
request.Parameters.Add(new Parameter() { Type = ParameterType.HttpHeader, Name = "Authorization", Value = authHeader });
try
{
var response = await _client.Execute(request);
string data = Encoding.UTF8.GetString(response.RawBytes, 0, response.RawBytes.Length);
var queryParameters = _magentoTools.FillFromString(data, true);
_oauthToken = queryParameters["oauth_token"];
_oauthTokenSecret = queryParameters["oauth_token_secret"];
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// Navigate to OAuth login page, extract form post URL and submit user credentials.
/// Upon redirection, store the redirection url in preparation for extraction of the new tokens.
/// </summary>
public async Task OAuthAuthorize()
{
var webClient = new HttpClient();
var loginUrl = new Uri(_client.BaseUrl.ToString() + MagentoService.Trim('/') + "/oauth/authorize" + "?oauth_token=" + _oauthToken).ToString();
// Get the login page and find the form post action url and the formkey
var loginPage = new HtmlDocument();
using (var responseStream = await webClient.GetStreamAsync(loginUrl))
{
loginPage.Load(responseStream);
}
var loginForm = loginPage.GetElementbyId("login-form");
var postUrl = loginForm.GetAttributeValue("action", string.Empty);
// Post the user credentials to the post action url
var postRequest = (HttpWebRequest)WebRequest.Create(postUrl);
postRequest.Method = "POST";
postRequest.ContentType = "application/x-www-form-urlencoded";
postRequest.CookieContainer = new CookieContainer();
var postData = String.Format("login%5busername%5d={0}&login%5bpassword%5d={1}&oauth_token={2}", CustomerUsername, CustomerPassword, _oauthToken);
byte[] postDataBytes = Encoding.UTF8.GetBytes(postData);
using (var requestStream = await postRequest.GetRequestStreamAsync())
{
requestStream.Write(postDataBytes, 0, postDataBytes.Length);
}
using (var response = await postRequest.GetResponseAsync())
{
if (response.Headers["location"] == null) throw new Exception("location is null");
}
}
public async Task OAuthToken()
{
await Task.Yield();
}
}
I have created a C# client for the Magento REST API. It is not a PCL, but should work. It uses RestSharp. Code is at https://github.com/nickvane/Magento-RestApi
The client is made for backend integration with Magento without user interaction. The login procedure actually does some screen scraping. The authentication process is explained in detail at https://github.com/nickvane/Magento-RestApi/wiki/Authentication-steps
If the library cannot be compiled directly to a PCL, then you can surely copy lots of code. And any fixes are welcome as pull-request.