Implementing oauth in SugarCRM using .NET - php

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

Related

Auth0 "The JWT string must contain two dots"

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.

PHP : verify JWS with JWK (x5c)

Context: I want to implement payment with Payconiq. When the payment is done, Payconiq calls my API to give me payment information (status, etc).
I'm using Symfony and web-token/jwt-bundle to verify JWS.
1/ I use 'base64_decode' to get the header from the token (token format is like: header.payload.signature with an empty payload)
2/ I get the json JWKs from URL: the JWK that always seems to be used is like:
{
"kty": "EC",
"use": "sig",
"x5t#S256": "******************",
"crv": "P-256",
"kid": "kid.2021",
"alg": "ES256",
"x5c": [],
"x": *******,
"y": *******
3/ I want to verify the signature with this JWK. I do :
$serializerManager = new JWSSerializerManager([new CompactSerializer(),]);
$jws = $serializerManager->unserialize($token);
$isVerified = $jwsVerifier->verifyWithKey($jws, $jwk, 0, $payload);
(public function verifyWithKey(JWS $jws, JWK $jwk, int $signature, ?string $detachedPayload = null): bool)
My payload: body request sent by Payconiq (payment information).
$isVerified is always false.
I don't know if the problem comes from my payload or the way I use the library (documentation shows an example with a JWK like
{
"kty": "oct",
"k": "dzI6nbW4OcNF-AtfxGAmuyz7IpHRudBI0WgGjZWgaRJt6prBn3DARXgUR8NVwKhfL43QBIU2Un3AvCGCHRgY4TbEqhOi8-i98xxmCggNjde4oaW6wkJ2NgM3Ss9SOX9zS3lcVzdCMdum-RwVJ301kbin4UtGztuzJBeg5oVN00MGxjC2xWwyI0tgXVs-zJs5WlafCuGfX1HrVkIf5bvpE0MQCSjdJpSeVao6-RSTYDajZf7T88a2eVjeW31mMAg-jzAWfUrii61T_bYPJFOXW8kkRWoa1InLRdG6bKB9wQs9-VdXZP60Q4Yuj_WZ-lO7qV9AEFrUkkjpaDgZT86w2g'
}
There's is a "k" key and the result is ok (isVerified = true).
But with a JWK without "k" and with "x5c", isVerified still false.
Could someone please help me?
It looks like the verification failed because you have have forgotten to set the appropriate signature algorithm (ES256) in the $jwsVerifier object.
Find hereafter a valid example. Please change the JWK and token values with you data.
use Jose\Component\Core\AlgorithmManager;
use Jose\Component\Core\JWK;
use Jose\Component\Signature\Algorithm\ES256;
use Jose\Component\Signature\Serializer\CompactSerializer;
use Jose\Component\Signature\JWSVerifier;
$jwk = JWK::createFromJson('{"kty":"EC","crv":"P-256","x":"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU","y":"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0"}');
$token = 'eyJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q';
$serializerManager = new CompactSerializer();
$jws = $serializerManager->unserialize($token);
$algorithmManager = new AlgorithmManager([new ES256()]);
$jwsVerifier = new JWSVerifier($algorithmManager);
$isVerified = $jwsVerifier->verifyWithKey($jws, $jwk, 0);
if ($isVerified) {
var_dump('Signature is valid');
} else {
var_dump('Signature is NOT valid!');
}
In case the payload is detached from the token, you can set it as fourth parameter of the verifyWithKey method.
Note that it shall not be base 64 encoded.
<?php
use Jose\Component\Core\AlgorithmManager;
use Jose\Component\Core\JWK;
use Jose\Component\Signature\Algorithm\ES256;
use Jose\Component\Signature\Serializer\CompactSerializer;
use Jose\Component\Signature\JWSVerifier;
$jwk = JWK::createFromJson('{"kty":"EC","crv":"P-256","x":"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU","y":"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0"}');
$token = 'eyJhbGciOiJFUzI1NiJ9..DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q';
$payload = base64_decode('eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ');
$serializerManager = new CompactSerializer();
$jws = $serializerManager->unserialize($token);
$algorithmManager = new AlgorithmManager([new ES256()]);
$jwsVerifier = new JWSVerifier($algorithmManager);
$isVerified = $jwsVerifier->verifyWithKey($jws, $jwk, 0, $payload);
if ($isVerified) {
var_dump('Signature is valid');
} else {
var_dump('Signature is NOT valid!');
}

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 connect phonegap app with php rest api

I have REST api on backend created with php (slim php micro framework). So code is:
INDEX.php
$app->post('/coords', 'authenticate', function() use ($app) {
$response = array();
//$jsonData = $app->request->post('podaci');
$jsonData = #file_get_contents('php://input');
$aData = json_decode($jsonData);
$latitude = $aData->location->latitude;
$longitude = $aData->location->longitude;
$podaci = $latitude.' ddd '.$longitude;
global $user_id;
$db = new DbHandler();
// creating new task
$coords_id = $db->createCoords($user_id, $podaci);
if ($coords_id != NULL) {
$response["error"] = false;
$response["message"] = "Coords insert successfully";
echoRespnse(201, $response);
} else {
$response["error"] = true;
$response["message"] = "Coords not inserted";
echoRespnse(200, $response);
}
});
I also have DBhandler file , code (function createCoords):
public function createCoords($user_id, $podaci) {
$stmt = $this->conn->prepare("INSERT INTO coords(podaci) VALUES(?)");
$stmt->bind_param("s", $podaci);
$result = $stmt->execute();
$stmt->close();
}
I try this REST api with sample data with ajax request and work well, but now I need to POST data from phonegap app to server and I write:
// BackgroundGeoLocation is highly configurable.
bgGeo.configure(callbackFn, failureFn, {
url: 'http://agroagro.com/agroMobile/v1/coords', // <-- Android ONLY: your server url to send locations to
params: {
Auth: 'df6017abde2d2re560896b63a0ee1039', // <-- Android ONLY: HTTP POST params sent to your server when persisting locations.
foo: 'bar' // <-- Android ONLY: HTTP POST params sent to your server when persisting locations.
},
desiredAccuracy: 0,
stationaryRadius: 50,
distanceFilter: 50,
notificationTitle: 'Background tracking', // <-- android only, customize the title of the notification
notificationText: 'ENABLED', // <-- android only, customize the text of the notification
activityType: 'AutomotiveNavigation',
debug: true, // <-- enable this hear sounds for background-geolocation life-cycle.
stopOnTerminate: false // <-- enable this to clear background location settings when the app terminates
});
I read here how to make php file to get INPUT data: https://github.com/christocracy/cordova-plugin-background-geolocation/issues/79
as you can see from my index.php code I write everything fine but what can be problem? This just dont work when I test on my android phone.
I do not why you are using 'php://input'); for getting json data.
Its simple. use the following to grab the json data sent from your phone.
$request = $app->request();
$body = $request->getBody();
$input = json_decode($body);
To know more how to handle json data using slim you may try the following website.
http://www.ibm.com/developerworks/library/x-slim-rest/

2 legged oath request without command line

i want to make an 2 legged oauth yql request with php.
So far:
// Include the PHP SDK.
include_once("yosdk/lib/Yahoo.inc");
// Define constants to store your API Key (Consumer Key) and
// Shared Secret (Consumer Secret).
define("API_KEY","her_comes the key");
define("SHARED_SECRET","here_comes_the_secret");
$two_legged_app = new YahooApplication(API_KEY,SHARED_SECRET);
$stock_query = "elect * from ......";
$stockResponse = $two_legged_app->query($stock_query);
var_dump($stockrResponse);
But the problem is, that i dont want to query the command line..... i just want to oauth with the api key i got and use the url directly i got of the command when i typed in yql....
like this:
$url='http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20('+url_stocks+')&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys';
(i edited the url that came out my wishes for).Please dont ask why i dont use the command to query (long story). i would be pleased by getting some help.
thanks.
solved it:
http://code.google.com/p/oauth-php/wiki/ConsumerHowTo
include_once "oauth/library/OAuthStore.php";
include_once"oauth/library/OAuthRequester.php";
$key_1 = "your_key"; $secret_1 = "your_secret";
$ticks="%22AAPL%22%2C%22MSFT%22";
$options = array( 'consumer_key' => $key_1, 'consumer_secret' =>
$secret_1 ); OAuthStore::instance("2Leg", $options );
$url =
"http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20('$ticks')&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys";
// this is the URL of the request $method = "GET"; // you can also use
POST instead $params = null;
try {
// Obtain a request object for the request we want to make
$request = new OAuthRequester($url, $method, $params);
// Sign the request, perform a curl request and return the results,
// throws OAuthException2 exception on an error
// $result is an array of the form: array ('code'=>int, 'headers'=>array(), 'body'=>string)
$result = $request->doRequest();
$response = $result['body'];
$resp_array=json_decode($response,TRUE);
echo $resp_array['query']['results']['quote'][1]['symbol']; // MSFT
} catch(OAuthException2 $e) { }

Categories