Auth0 "The JWT string must contain two dots" - php

I'm currently using Vue3 and have integrated Auth0-spa-js from https://github.com/auth0/auth0-spa-js. This works great.
I'm sending requests to a PHP API backend through Axios, passing in the access token as a GET parameter called token.
Server side I get an exception "The JWT string must contain two dots" after setting up steps from https://github.com/auth0/auth0-PHP. I've installed the requirements, guzzle and dotenv, etc. Currently on PHP 7.4.2.
// useAuth0.js
// to login and maintain Auth state
import createAuth0Client from "#auth0/auth0-spa-js";
import { reactive } from "vue";
export const AuthState = reactive({
user: null,
loading: false,
isAuthenticated: null,
auth0: null,
});
const config = {
domain: import.meta.env.VITE_AUTH0_DOMAIN,
client_id: import.meta.env.VITE_AUTH0_CLIENT_ID,
};
export const useAuth0 = (state) => {
const handleStateChange = async () => {
state.isAuthenticated = !!(await state.auth0.isAuthenticated());
state.user = await state.auth0.getUser();
state.loading = false;
};
const initAuth = () => {
state.loading = true;
createAuth0Client({
domain: config.domain,
client_id: config.client_id,
cacheLocation: "localstorage",
redirect_uri: window.location.origin,
}).then(async (auth) => {
state.auth0 = auth;
await handleStateChange();
});
};
const login = async () => {
await state.auth0.loginWithPopup();
await handleStateChange();
};
const logout = async () => {
state.auth0.logout({
returnTo: window.location.origin,
});
};
return {
login,
logout,
initAuth,
};
};
// and I use this on a button click event
AuthState.auth0.getTokenSilently().then(accessToken => {
// AXIOS REQUEST
})
// PHP
// Auth0 SDK is 8.1.0
use Auth0\SDK\Auth0;
use Auth0\SDK\Utility\HttpResponse;
use Auth0\SDK\Token;
$env = (Dotenv\Dotenv::createImmutable(FCPATH))->load();
// I've checked that $env does contain correct .env values
$token = filter_var($_GET['token'] ?? null, FILTER_UNSAFE_RAW, FILTER_NULL_ON_FAILURE);
// Actual token I logged
eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwiaXNzIjoiaHR0cHM6Ly9kZXYtd2kxeGRtbDcudXMuYXV0aDAuY29tLyJ9..V50FRJnBnpBnHJjA.e3PZuESoGaPCjp0kO9vlijGMIfhXWQHlbvsslWtbAvFAQ5hef9_PXLD_W282Cba9D6k-FAwhro9i3e5ukzXouGWYfoYHHQ5WQJ-vpLISrRANxFvNVPsCZSkg1sAIbL0Qk3Gir82ds1G919uEPc6vB3Y2qbARAd9nlMJBpLqWUq9VcIrzHtsJN7Q8j36vTCRXyu0f5-TeOr-dU3-gaIUvur37YQD0xICr4sENFktPU3s-uqCSCopVi6MoZMGvfYcVlO3nv1Sb2owGX_S_PSG7fug4Et-pMw1cVYgfNtLQf8XViI-l19sgXAf2eQShmLPvcdBdXVPA0g.S9vyktmK7rPoM_F3nUSEvg
$auth0 = new Auth0([
'domain' => $env['AUTH0_DOMAIN'],
'clientId' => $env['AUTH0_CLIENT_ID'],
'clientSecret' => $env['AUTH0_CLIENT_SECRET'],
'tokenAlgorithm' => 'RS256'
]);
// Exception thrown here with decode
$token = $auth0->decode($token, null, null, null, null, null, null, Token::TYPE_ID_TOKEN);
$token->verify();
$token->validate();
Is there and issue with auth0-spa-js when creating the token thats not compatible with Auth0 PHP SDK, or a configuration setting is not being passed that I need to add? I've pretty much configured things as those two docs specify, double checking expected variables.

Turns out I needed to add the audience parameter to the createAuth0Client, getTokenSilently(), and the PHP SDK decode method for my Auth0 Custom API. Everything validated.
I must of missed something in the docs, or it seems that the audience parameter is more of a required than optional value.

Adding to Brian Barton's answer above, the GetTokenSilentlyOptions interface explains that the options should be passed as follows:
// ✅ Like this!
const token = await this.$auth.getTokenSilently({
authorizationParams: {
audience: 'https://api.example.com/',
},
})
// ❌ NOT like this (where I got stuck for a while)
const token = await this.$auth.getTokenSilently({
audience: 'https://api.example.com/',
})
It wasn't immediately obvious to me that the additional outer object structure was required so I couldn't figure out why I couldn't get their solution to work.
Additional Context
This has NOTHING to do with what you have on the server side and everything to do with how your SPA retrieves your JWT tokens following the Authorization Code Flow with Proof Key for Code Exchange (PKCE) (which is the flow you should be using if you're accessing an API from an SPA).
I ended up finding this answer because when I failed to set the audience parameter correctly, Auth0 did NOT signal that there were any errors whatsoever. It returned a "token" that NOT a well-formed JWT. In my case it consistently had four or five dots (periods) when there should have been exactly two.

Related

Firebase Create Custom Token on php always returns null on php

Hi I am using cakephp as backend and want to generate a custom token for my website which will be used on my client side.
Below is my code to generate a custom code
$activatedOfferwall = $session->read('ActiveOfferwall'); // 0209341c-da14-46b9-b3c9-8410472e13d2
$factory = (new Factory)->withServiceAccount(\App\Model\Constants\FirebaseConstants::JSON_FILE)->withDatabaseUri(\App\Model\Constants\FirebaseConstants::DEFAULT_URL);
$auth = $factory->createAuth();
$customToken = $auth->createCustomToken($activatedOfferwall['UserHash']);
Log::debug(json_encode($customToken));
and the fire base rules are
but this always returns an empty json. What am I missing here?
For someone who is looking, I found the solution. Rules had to be
$generator = CustomTokenGenerator::withClientEmailAndPrivateKey(
$email,
$privateKey
);
$token = $generator->createCustomToken('anthony#gmail.com');
and then send the token on the client side
firebase.auth().signInWithCustomToken(usertoken)
.then((userCredential) => {
// Signed in
var user = userCredential.user;
firebase.auth().currentUser.getIdToken( /* forceRefresh */ true).then(function(idToken) {
console.log(idToken)
}).catch(function(error) {
// Handle error
});
})
.catch((error) => {
var errorCode = error.code;
var errorMessage = error.message;
console.log(error);
// ...
});
it's not only about the rules. if you are using the package kreait/laravel-firebase (https://firebase-php.readthedocs.io/en/stable/overview.html)
you will have to get the token with it's own method like this:
$firebaseCustomToken = $firebaseAuth->createCustomToken($user->id);
$CustomToken = $firebaseCustomToken->toString(); // like this will return the customToken
hope this helps someone
Reference of the git change here: https://github.com/kreait/firebase-php/commit/8b45c07d922364ba9298fa07cbe7ea676c1d05f4

How to handle multiple environments: dev, staging and production with paypal webhooks?

I would like to have three environments, where I can test and use paypal webhooks. My current approach is to create new webhook for every environment in paypal developer portal and when request arrives check if it is for that environment. How does paypal handle multiple webhook urls and what status code should be returned if environment is not correct?
Create a Class like below to keep in the beginning of your application. Let it initialize once.
class App {
private static $env_status = null;
private static $paypal_settings = [];
const ENV_PRODUCTION = "production";
const ENV_STAGING = "staging";
const ENV_DEV = "development";
public static function init() {
// Set environment status.
// You can also parse domain name and depending on your domain, you can set the environment status.
self::$env_status = getenv("ENV_STATUS"); // getenv() Gets from Environment variable. You'll need set clear_env = no in php config for this to work.
switch(self::$env_status) {
case App::ENV_PRODUCTION:
self::$paypal_settings = [
"mode" => "live"
"clientID" => "PRODUCTION_CLIENT_ID" ,
"secret" => "PRODUCTION_SECRET" ,
"currency" => "USD",
"webhook" => "https://example.com/live_webhook_endpoint"
];
break;
case App::ENV_STAGING:
self::$paypal_settings = [
"mode"=> "sandbox"
"clientID"=> "STAGING_CLIENT_ID" ,
"secret"=> "STAGING_SECRET" ,
"currency"=> "USD",
"webhook" => "https://example.com/staging_webhook_endpoint"
];
break;
default:
// ENV_DEV settings
self::$paypal_settings = [
"mode"=> "sandbox"
"clientID"=> "DEVELOPMENT_CLIENT_ID" ,
"secret"=> "DEVELOPMENT_SECRET" ,
"currency"=> "USD",
"webhook" => "https://example.com/development_webhook_endpoint"
];
break;
}
}
public static function env_status() {
return self::$env_status;
}
public static function paypal_settings() {
return self::$paypal_settings;
}
// You can also create seprate function if you just want webhook URL.
// You can define in different variable also if that's the case.
public static function paypal_webhook_url() {
return self::$paypal_settings['webhook'];
}
} App::init();
Then whenever you want to get paypal settings you can call it from anywhere in your Application.
$paypay_settings = App::paypal_settings();
OR if you need just paypal webhook URL
$paypal_webhook_url = App::paypal_webhook_url();
This way you don't have to keep any conditions in other parts of your code. All the conditions will go in a single place, which will be easier to update later.
How does paypal handle multiple webhook urls.
You will need to hit PayPal Sandbox URL to hit for staging/development environment.
What status code should be returned if environment is not correct?
HTTP 400. Since it will be an invalid request.
Ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400
The HyperText Transfer Protocol (HTTP) 400 Bad Request response status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).
On one of our projetcs, we use different configuration variables depending on the environnement.
For dev
$config['paypal.settings'] = array(
'mode'=> "sandbox", //'live' or 'sandbox'(default)
'clientID'=>"CLIENT_ID_FOR_DEV" ,
'secret'=> "SUPERSECRETCLIENT_SECRET_FOR_DEV" ,
'currency'=>'EUR',
'logEnabled' => false,
'logDir'=>__DIR__ . '/../logs'
);
For prod :
$config['paypal.settings'] = array(
'mode'=> "live",
'clientID'=>"CLIENT_ID_FOR_PROD" ,
'secret'=> "SUPERSECRETCLIENT_SECRET_FOR_PROD" ,
'currency'=>'EUR',
'logEnabled' => false,
'logDir'=>__DIR__ . '/../logs'
);
and our dev and prod environnement are obviously on 2 different domains that are configured for each CLIENT_ID on the paypal interface.
In the webhook controller called by Paypal we have :
class WebhookController{
function paypalPingBackAction($request){
$paypalSettings = //get paypal settings
$isLive = ($paypalSettings["sandbox"] ?? "sandbox") == "live";
$currentDomain = $request->getDomain();
// now we have enough information (domain and sandbox)
// to do things accordingly
}
}
Paypal does not really care about what code you send back. But if you send a 500, he will retry later. So maybe, if things go well, just return an empty 201 accepted !

Finding User with Auth - Laravel

I am trying to find the logged in user in my application using Auth but i get trying to get property of non-object which i understand clearly that it is returning null.
In my code below, an event triggers my webhook and post is sent to the address below. The function orderCreateWebhook triggers but that is where the error comes from..
The line $get_template = Order::where('id', Auth::user()->id);. Why is Auth returning null please? I am logged as well because i use auth in this same controller for another function which works fine.
Is it because it a webhook ?
Controller
public function registerOrderCreateWebhook(Request $request)
{
$shop = "feas.myshopify.com";
$token = "8f43d89a64e922d7d343c1173f6d";
$shopify = Shopify::setShopUrl($shop)->setAccessToken($token);
Shopify::setShopUrl($shop)->setAccessToken($token)->post("admin/webhooks.json", ['webhook' =>
['topic' => 'orders/create',
'address' => 'https://larashop.domain.com/order-create-webhook',
'format' => 'json'
]
]);
}
public function orderCreateWebhook(Request $request)
{
$get_template = Order::where('id', Auth::user()->id);
$baseurl = "https://apps.domain.net/smsapi";
$query = "?key=7e3e4d4a6cfebc08eadc&to=number&msg=message&sender_id=Shopify";
$final_uri = $baseurl.$query;
$response = file_get_contents($final_uri);
header ("Content-Type:text/xml");
}
In your function registerOrderCreateWebhook you appear to be making a request to shopify api and providing your webhook as the address which shopify will redirect the user to upon success. If this is correct, that request does not know about the user who generated the original request that made the api request since the request is coming from a completely different origin.
You would need to pass some key along with the url and then obtain the user within orderCreateWebhook. Something like:
Shopify::setShopUrl($shop)->setAccessToken($token)->post("admin/webhooks.json",
['webhook' =>
['topic' => 'orders/create',
'address' => 'https://larashop.domain.com/order-create-webhook/some-unique-key',
'format' => 'json'
]
]);
My suggestion would be to have a unique hash stored somewhere that relates back to the user in your system, perhaps a column in your users table. I wouldn't use the user_id for security reasons. So you would end up with something like:
//route
Route::get('/order-create-webhook/{uniqueKey}', 'YourController#orderCreateWebhook');
//or
Route::post('/order-create-webhook/{uniqueKey}', 'YourController#orderCreateWebhook');
// depending on the request type used by api which calls this endpoint
// controller function
public function orderCreateWebhook($uniqueKey, Request $request)
{
$user = User::where('unique_key', $uniqueKey)->first();
$get_template = Order::where('id', Auth::user()->id);
$baseurl = "https://apps.domain.net/smsapi";
$query = "?key=7e3e4d4a6cfebc08eadc&to=number&msg=message&sender_id=Shopify";
$final_uri = $baseurl.$query;
$response = file_get_contents($final_uri);
header ("Content-Type:text/xml");
}
Is it because it a webhook ?
Yes, you can't use sessions in a webhook. It's the shopify server which is making the call. You should read the doc, it may exist a way to give an unique identifier in your call to shopify api and get it back in the webhook to find your user associated.
just use this to get authenticated user
use the facade in your class/Controller
use Illuminate\Support\Facades\Auth
public function getAuthUser(){
$user = Auth::user()
if(!is_null($user)
{
//user is authenticated
}
else
{
// no user
}
}

Bearer error="invalid_token" from .net core 2.0

I have an authentication system set up in PHP that I am trying to use to send JSON Web Tokens to a client app in order for the app to access a .net core 2.0 api. So the authentication server takes user credentials and if the credentials pass, it generates the token using a public/private key pair I created with openssl. I am generating the token using the procedure here: http://www.phpbuilder.com/articles/application-architecture/security/using-a-json-web-token-in-php.html
I can decode the resulting token with jwt.io just fine. The decoded version looks like this:
{
"typ": "JWT",
"alg": "HS256"
}
{
"iss": "https://crm.advtis.com",
"exp": "2017-12-21 18:14:42",
"aud": "https://localhost:44354",
"data": {
"username": "pwalter#advtis.com",
"role": 1
}
}
I can enter the string from my private key file, which was used to encode the token, and jwt.io says the signature is valid.
So now I want to send the token along with a request to my API to gain access to that resource, which while debugging is found on localhost. Here is the .NET 2.0 startup code relevant to that:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<SmartRxDBContext>();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Audience = "https://localhost:44354/";
options.TokenValidationParameters = new TokenValidationParameters {
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidIssuer = "https://crm.advtis.com/",
IssuerSigningKey = new X509SecurityKey(new X509Certificate2("C:\\Path\\To\\webOrders-cert-AspNetPubkey.cert"))
};
});
services.AddMvc();
}
The path referenced is to a pem formatted public key I generated, also using openssl, from the private key used to encode the jwt. I was trying to follow this example for the .NET Core piece - JWT Validation and Authorization in ASP.NET Core
- but of course the whole auth middleware configuration has been moved in 2.0 to the ConfigureServices method, and there is no longer an AutomaticAuthorization option.
Everything seems to be fine, but I am getting a 401 - Unauthorized Bearer error="invalid_token" error when making a request with the header as Authorization: Bearer TOKEN Anyway, I was hoping someone could give me some advice as to where I might be going wrong and/or how I could troubleshoot further.
So, I got this figured out for anyone wanting to run this same type of scenario.
My first problem was that I was using HMAC to generate the tokens on the PHP side. HMAC is not a public/private pair algorithm. I installed the firebase/php-jwt library with composer, and used that to generate my token like this:
use \Firebase\JWT\JWT;
$token = array(
"iss" => "https://crm.advtis.com",
"exp" => time()+10000,
"aud" => "https://localhost:44354",
"data" => array(
"username" => "pwalter#advtis.com",
"role" => 1
)
);
$jwt = JWT::encode($token, file_get_contents("../path/to/private.key"), 'RS256');
The key file was generated on the command line with OpenSSL. I used the same utility to generate a public key with the private key. Both files are in PEM format.
The next thing I had to do was get the public key into .NET. The easiest way I found to do use an RSACryptoServiceProvider, sort of like this:
private static RSACryptoServiceProvider myRSA = new RSACryptoServiceProvider();
public void ConfigureServices(IServiceCollection services)
{
JwtHelper.FromXmlString(myRSA, "C:\\Users\\Path\\To\\xmlPubKey.xml");
services.AddDbContext<SmartRxDBContext>();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters {
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidIssuer = "https://crm.advtis.com",
ValidateAudience = true,
ValidAudience = "https://localhost:44354",
IssuerSigningKey = new RsaSecurityKey(myRSA.ExportParameters(false))
};
});
services.AddMvc();
}
The JwtHelper.FromXml() method was adapted from here, because there is no way in .NET 2.0 to import or set parameters from XML within the RSA Provider, so that method parses the XML and sets the parameters like so:
public static void FromXml(this RSA rsa, string filepath)
{
RSAParameters parameters = new RSAParameters();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(filepath);
if (xmlDoc.DocumentElement.Name.Equals("RSAKeyValue"))
{
foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes)
{
switch (node.Name)
{
case "Modulus": parameters.Modulus = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
case "Exponent": parameters.Exponent = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
case "P": parameters.P = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
case "Q": parameters.Q = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
case "DP": parameters.DP = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
case "DQ": parameters.DQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
case "InverseQ": parameters.InverseQ = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
case "D": parameters.D = (string.IsNullOrEmpty(node.InnerText) ? null : Convert.FromBase64String(node.InnerText)); break;
}
}
}
else
{
throw new Exception("Invalid XML RSA key.");
}
rsa.ImportParameters(parameters);
}
So that's the gist of it. Now I can issue JWTs from my PHP server to a client application. Then I can send the JWTs over to my .NET Core 2.0 API to get access to endpoints protected by [Authorize] attribute.

Implementing oauth in SugarCRM using .NET

I have a web application developed in .net framework. I am trying to implement Oauth in sugarCRM in order to integrate it with my applications.
The Oauth mechanism given by sugarCRM is using PHP Click Here...
where as, my application is designed in ASP.
I am trying to figure out solution (like converting php code to asp or implementing the same mechanism in my application) for same but got no solution.any help would be appreciated.
after much pain, I've got my .Net Code working on SugarCRM.....
This is what I did....all in a Console app for me. This a proof of concept and so everthing is hard coded for now!
Use Nuget to Install OAuth by Daniel Crenna
Step 1: Establish Consumer Key
Go into Admin -> OAuth Keys section on SugarCRM and create a new record, I used Key & Secret.
Step 2: Creating a Request Token
private static void CreateRequestToken()
{
// Creating a new instance directly
OAuthRequest client = new OAuthRequest
{
Method = "GET",
Type = OAuthRequestType.RequestToken,
SignatureMethod = OAuthSignatureMethod.HmacSha1,
ConsumerKey = "Key",
ConsumerSecret = "Secret",
RequestUrl = "http://localhost/service/v4/rest.php",
Version = "1.0",
SignatureTreatment = OAuthSignatureTreatment.Escaped
};
// Using URL query authorization
string auth = client.GetAuthorizationQuery(new Dictionary<string, string>() { { "method", "oauth_request_token" } });
var request = (HttpWebRequest)WebRequest.Create("http://localhost/service/v4/rest.php?method=oauth_request_token&" + auth);
var response = (HttpWebResponse)request.GetResponse();
NameValueCollection query;
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
string result = sr.ReadToEnd();
query = HttpUtility.ParseQueryString(result);
}
Console.WriteLine(query["authorize_url"]);
Console.WriteLine(query["oauth_token"]);
Console.WriteLine(query["oauth_token_secret"]);
}
This is the tricky part that took me ages to figure out, notice the requesturl is without the query part in the client, and you have add it to the GetAuthorizationQuery call AND to the actual WebRequest url.
Note down the 3 items ready for Step 4.
Step 3 Approve Request Token
Visit the url "authorize_url" above and also add &token= "oauth_token". For this was:
http://localhost/index.php?module=OAuthTokens&action=authorize&token=adae15a306b5
Authorise the token and record the Token Authorisation Code.
Step 4 Request Access Token
private static void RequestAccessToken()
{
OAuthRequest client = new OAuthRequest
{
Method = "GET",
Type = OAuthRequestType.AccessToken,
SignatureMethod = OAuthSignatureMethod.HmacSha1,
ConsumerKey = "Key",
ConsumerSecret = "Secret",
RequestUrl = "http://localhost/service/v4/rest.php",
Version = "1.0",
SignatureTreatment = OAuthSignatureTreatment.Escaped,
Token = "adae15a306b5",
TokenSecret = "e1f47d2a9e72",
Verifier = "33e2e437b2b3"
};
// Using URL query authorization
string auth = client.GetAuthorizationQuery(new Dictionary<string, string>() { { "method", "oauth_access_token" } });
var request = (HttpWebRequest)WebRequest.Create("http://localhost/service/v4/rest.php?method=oauth_access_token&" + auth);
var response = (HttpWebResponse)request.GetResponse();
NameValueCollection query;
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
string result = sr.ReadToEnd();
query = HttpUtility.ParseQueryString(result);
}
Console.WriteLine(query["oauth_token"]);
Console.WriteLine(query["oauth_token_secret"]);
}
Token and TokenSecret are from Step 2, Verifier is the Auth Code from Step 3.
Step 5 Use the Access Token
I'm just using the session id as Recommended by the Documentation, so to get the sessionId
private static void GetSessionId()
{
OAuthRequest client = new OAuthRequest
{
Method = "GET",
Type = OAuthRequestType.ProtectedResource,
SignatureMethod = OAuthSignatureMethod.HmacSha1,
ConsumerKey = "Key",
ConsumerSecret = "Secret",
RequestUrl = "http://localhost/service/v4/rest.php",
Version = "1.0",
SignatureTreatment = OAuthSignatureTreatment.Escaped,
Token = "adae15a306b5",
TokenSecret = "2d68ecf5152f"
};
string auth = client.GetAuthorizationQuery(new Dictionary<string, string>()
{
{ "method", "oauth_access" },
{ "input_type", "JSON" },
{ "request_type", "JSON" },
{ "response_type", "JSON" }
});
var request = (HttpWebRequest)WebRequest.Create("http://localhost/service/v4/rest.php?method=oauth_access&input_type=JSON&request_type=JSON&response_type=JSON&" + auth);
var response = (HttpWebResponse)request.GetResponse();
dynamic o;
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
string result = sr.ReadToEnd();
o = Newtonsoft.Json.JsonConvert.DeserializeObject(result);
}
Console.WriteLine("SessionId: {0}", o.id);
}
Here I'm using JSON.Net to parse the Json into a dynamic object for easy access to the id.
Step 6 Make it do something....
Over to you!
Pretty painful experience, but at least its working for me.....
Tim
I didn't get what you meant by implementing in SugarCRM way. But if you can't use dotnetopenauth, you can spin your own OAuth using RestSharp or Hammock

Categories