I have a small app that uses (used) OAuth Echo in conjunction with Tweetbot's custom image endpoint to self-host media I post to Twitter. The recent API update has broken the app and I can't seem to find any information on how to fix it.
Here is the class I was using prior to the update:
// Twitter oAuth Echo Class
// Author: http://shikii.net/blog/creating-a-custom-image-service-for-twitter-for-iphone/
class namespace_TwitterOAuthEcho
{
public $verificationUrl = "https://api.twitter.com/1/account/verify_credentials.json";
//isset($_SERVER['X-AUTH-SERVICE-PROVIDER']) ? $_SERVER['X-AUTH-SERVICE-PROVIDER'] : false;
public $userAgent = __CLASS__;
public $verificationCredentials;
/**
*
* #var int
*/
public $resultHttpCode;
/**
*
* #var array
*/
public $resultHttpInfo;
public $responseText;
/**
* Save the OAuth credentials sent by the Consumer (e.g. Twitter for iPhone, Twitterrific)
*/
public function setCredentialsFromRequestHeaders()
{
$this->verificationCredentials = isset($_SERVER['HTTP_X_VERIFY_CREDENTIALS_AUTHORIZATION'])
? $_SERVER['HTTP_X_VERIFY_CREDENTIALS_AUTHORIZATION'] : false;
}
/**
* Verify the given OAuth credentials with Twitter
* #return boolean
*/
public function verify()
{
$curl = curl_init($this->verificationUrl);
curl_setopt($curl, CURLOPT_USERAGENT, $this->userAgent);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Authorization: ' . $this->verificationCredentials,
));
$this->responseText = curl_exec($curl);
$this->resultHttpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
$this->resultHttpInfo = curl_getinfo($curl);
curl_close($curl);
return $this->resultHttpCode == 200;
}
}
As a twitter API novice, I'm not certain what to change to get it working again. Twitter's OAuth Echo documentation hasn't been updated since Aug. 2012, so that's of no help.
Twitter's API 1.1 Overview page does say that all endpoints now require authorization. Fine. I set up a new app; got my Consumer key/secret. I'm not certain where those go, however. When editing the application settings on Twitter, I'm also not certain what settings should be in place here. My app doesn't (in my opinion) actually need to interact with Twitter. I'm just trying to send a URL back to Tweetbot (any twitter client) so it can place it in the tweet.
Any help in getting this updated would be much appreciated. Thank you.
Replace
public $verificationUrl = "https://api.twitter.com/1/account/verify_credentials.json";
with
public $verificationUrl = "https://api.twitter.com/1.1/account/verify_credentials.json";
Thats it. You just need to change the URL only. There is no need to change in your twitter APP also. It will work with you old APP also.
Related
After having connected a user from Google OAuth, when this one wishes to reconnect during a next session requiring the selection of his google account, the permission is asked again.
According to the documentation, the behavior of the parameter prompt that is responsible for authorization requests is as follows:
If no value is specified and the user has not previously authorized
access, then the user is shown a consent screen.
The user should therefore not have to reorder his consent.
The only answer envisaged was the one on this question : login with google always asks user consent
Because I also work locally without secure HTTP, but he assumes that a cookie policy is present which is not the case.
How could I do to resolve this anomaly ?
Edit :
/**
* Create a new OAuth2Client with the credentials previously loads
*/
private getOAuth2() : OAuth2Client {
return new OAuth2(
this.credentials.client_secret,
this.credentials.client_id,
this.credentials.redirect_uris[0]
);
}
/**
* Create connection URL for the given scopes
* #param scopes
*/
public url(scopes: Array<string>) : string {
return this.client.generateAuthUrl({
access_type: "offline",
scope: scopes
});
}
// The scope used to generate URL is 'https://www.googleapis.com/auth/youtube.readonly'
// this.client refer to a client which is load by getOAuth2
// and use only for the generation of URL's.
Can anyone advice me how can I add Moneris payment metnod with laravel 5.1 ?
I have a merchant account. But I am not sure if laravel supports monaris or not.
Thanks in advance.
Laravel by itself doesn't support Moneris (nor any payment processor). However, you can integrate Moneris (and the Moneris API) into your Laravel application by following the directives listed on their developer portal.
Compared to modern payment solutions, such as Stripe or Braintree, Moneris' API can be pretty tedious to use. If you are only using basic purchase, verify, preauth, capture, and refund operations, I suggest you to check out Keith Silgard's library.
However, if you need to implement other operations, such as adding a card to the Vault, you will have to follow Moneris' examples and adapt them to fit into your Laravel Application. For (a very rough) example:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use mpgClasses;
class PaymentController extends Controller
{
protected function addCardToMonerisVault(Request $request) {
/**************************** Request Variables *******************************/
$store_id=getenv('MONERIS_STORE_ID');
$api_token=getenv('MONERIS_API_KEY');
/************************* Transactional Variables ****************************/
$type='res_add_cc';
$cust_id= Auth::user()->id;
$pan=preg_replace('/\D/', '', $request->input('number'));
$expiry_date=$request->input('expiry_year') . $request->input('expiry_month');
$crypt_type='1';
$avs_street_number = '';
$avs_street_name = '';
$avs_zipcode = '';
/*********************** Transactional Associative Array **********************/
$txnArray=array('type'=>$type,
'cust_id'=>$cust_id,
'pan'=>$pan,
'expdate'=>$expiry_date,
'crypt_type'=>$crypt_type
);
/**************************** Transaction Object *****************************/
$mpgTxn = new \mpgTransaction($txnArray);
/****************************** Request Object *******************************/
$mpgRequest = new \mpgRequest($mpgTxn);
/***************************** HTTPS Post Object *****************************/
$mpgHttpPost =new \mpgHttpsPost($store_id,$api_token,$mpgRequest);
/******************************* Response ************************************/
$response = $mpgHttpPost->response;
return $response;
}
}
My server side breeze api calls require me to validate the token value provided with each call before returning any data. To achieve this, i am passing TokenId with each Entity Query using withParameters function of breeze Entity Query and specify the parameter on my server side controller action as illustrated below.
Following is how i am doing it right now:
Client Side
function GetCustomers(){
return breeze.EntityQuery.from('Customers')
.withParameters({ TokenId: 'token value' })
.using(entityManager).execute()
}
Server Side
[HttpGet]
public IQueryable<Customer> Customers(string TokenId)
{
//server side logic
}
This for some reason looks to me can be simplified using some configuration on Breeze Entity Manager which automatically adds the parameter value to every query sent from client. And also, on server side, i don't think its necessary to have tokenId parameter defined on each controller method. This should be easy to solve with Action Filters on the server side.
Can someone point me in right direction if it is possible and how to do this?
Thanks
You should always pass custom authentication information, such as tokens, in the headers.
If you can pass it as a custom header you can search for 'define custom headers breeze.js' to see how that can be done.
A good example -
http://breeze.github.io/doc-js/server-ajaxadapter.html
Also keep in mind that if you put the token in the query string that is persisted by most of the servers that your call is crossing over, making it much easier to find tokens for your application if an evil-doer were to download the logs from that server.
Also keep in mind that if you are using cross-domain requests (CORS) you will need to enable the custom header on the server side that is receiving the call.
To give an example of the answer above:
// get the current default Breeze AJAX adapter
var ajaxAdapter: any = breeze.config.getAdapterInstance('ajax');
// set fixed headers
ajaxAdapter.defaultSettings = {
headers: {
"Bearer": this.bearerToken
}
};
Note also that if you are using ASP.net Identity (which includes a cookie based authentication), you must include this code so that the asp.net pipeline does NOT use that cookie:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Filters.Add(new Ask.Filters.RequireHttpsAttribute());
//This forces http header authentication which is required for web api calls.
config.SuppressDefaultHostAuthentication();
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
Note also that you should use only https, with this filter:
public class RequireHttpsAttribute : AuthorizationFilterAttribute
{
public int Port { get; set; }
public RequireHttpsAttribute()
{
Port = 443;
}
public override void OnAuthorization(HttpActionContext actionContext)
{
var request = actionContext.Request;
if (request.RequestUri.Scheme != Uri.UriSchemeHttps)
{
var response = new HttpResponseMessage();
if (request.Method == HttpMethod.Get || request.Method == HttpMethod.Head)
{
var uri = new UriBuilder(request.RequestUri);
uri.Scheme = Uri.UriSchemeHttps;
uri.Port = this.Port;
response.StatusCode = HttpStatusCode.Found;
response.Headers.Location = uri.Uri;
}
else
{
response.StatusCode = HttpStatusCode.Forbidden;
}
actionContext.Response = response;
}
else
{
base.OnAuthorization(actionContext);
}
}
}
And finally, make sure you use the [Authorize] and [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)] attribute on your controllers.
See the Full Sample and article on asp.net
I suggest using oAuth tokens in the header. I am currently using Auth0, but there are many others including Google Firebase. BreezeJS has been expanded such that it will accept AuthHttp as it's HTTP client for all calls. AuthHttp will automatically add a bearer token to the header of every call to the server.
One the server side it's a matter of adding the proper oAuth client lib (via Nuget) which automatically parses out the bearer token, validates it against the oAuth server, and makes claims available for use within your API call.
For example, in my implementation my api code will receive a claim that contains the users id, which I can then validate against my db and use to filter all actions. This keeps user B from loading user A's data by directly calling the api in a browser.
For example, all API calls are first validated by the oAuth subsystem. Once my api code is executed I know the caller has been validated and I use the passed claims (user id) to access only the calling users data - REGARDLESS what was actually requested by the API call parameters (which can be forged as easily as editing a URL string).
A simple example of this would be exposing your UserSet in the API. If you don't filter by the user claim id you must realize that every user in your system will be accessible by constructing a simple URL in a browser.
Here I filter out and return only the user record identified by the user id in the auth claim. Note I use #if AUTH simply for testing as PROD will always have AUTH turned on.
#if AUTH
[Authorize]
#endif
[HttpGet]
[EnableBreezeQuery(MaxExpansionDepth = 5)]
public IQueryable<User> UserSet()
{
#if AUTH
Guid guid = userGuid();
return _efContext.Context.UserSet.Where(x => x.active && x.guid == guid);
#else
return _efContext.Context.UserSet;
#endif
}
All of this sounds complicated, but it really is quite easy to implement.
Thanks,
Mike
I'm trying to implement OAuth with twitter so my users can log into my site using their Twitter IDs. For this I am using the TweetSharp library. Following the examples they have I wrote the following code which seems to work.
public ActionResult Login(string oauth_token, string oauth_verifier)
{
var service = new TwitterService(consumerKey, consumerSecret);
if (oauth_token == null)
{
var requestToken = service.GetRequestToken(Request.Url.ToString());
var uri = service.GetAuthorizationUri(requestToken);
return new RedirectResult(uri.ToString(), false);
}
else
{
var requestToken = new OAuthRequestToken { Token = oauth_token };
OAuthAccessToken accessToken = service.GetAccessToken(requestToken, oauth_verifier);
service.AuthenticateWith(accessToken.Token, accessToken.TokenSecret);
TwitterUser user = service.VerifyCredentials(new VerifyCredentialsOptions());
TempData["response"] = string.Format("Your username is {0}", user.ScreenName);
return RedirectToAction("Success");
}
}
public ActionResult Success()
{
ViewBag.Response = TempData["response"];
return View();
}
However, there is a problem. Every time the user logs into the system twitter asks them to authorize the application even though they have done it before. Is there a way to prevent this behavior? I have also implemented OAuth with Facebook and Google and I don't need to authorize the application every time I want to log into the system.
Unfortunately not as far as I'm aware. Twitter uses OAuth 1.1 rather than OAuth 2.0 like Facebook and Google, so there is a manual step in the middle in which users are asked to authorise the application even though they have done already. I'm having exactly the same issue and it appears to be something we have to live with.
I was having the same problem with a slightly older app I was trying to resurrect. I noticed that the problem went away when I selected "Sign in with Twitter" in my app settings at http://dev.twitter.com/apps.
I have a symfony2 website and a web service secured via oauth using FOSOAuthServerBundle accessible via an iOS app. On the website I use FOSUserBundle and FOSFacebookBundle.
The only thing I miss is giving the possibility to the user to login with facebook on the iOS app and to return him an access_token for my oauth linked to his user account so that he can access my api like other users.
So basically I want to send the user facebookID and facebook_access_token to my webservice, check that the user is correct (token matches my app) and return an authentication token.
QUESTION: is there an easy way to add a "Facebook" grant_type to FOSOAuthServerBundle ?
I know some people have done this seeing these questions:
Design for Facebook authentication in an iOS app that also accesses a secured web service
Get application id from user access token (or verify the source application for a token)
But they do not explain how, they do not seem to use FOSOauthServerBundle and questions are quite old.
I have tried using this bundle:
https://github.com/TheFootballSocialClub/FSCOAuth2FacebookGrantBundle
but this bundle has been downloaded only 9 times before me and is not fully suited to my app (it considers that a Facebook user username equals his facebookId for instance). So I guess what I want to do is re-implement the same kind of thing my own way.
If anyone has already done that our could provide any guidance it would be very much appreciated.
Thank you
To do this, you have to add a Grant Extensions, see the official document "Adding Grant Extensions" : https://github.com/FriendsOfSymfony/FOSOAuthServerBundle/blob/master/Resources/doc/adding_grant_extensions.md
You can find my FacebookGrantExtension to get a token from a FB access_token :
class FacebookGrantExtension implements GrantExtensionInterface
{
protected $userManager = null;
protected $facebookSdk = null;
public function __construct(UserManager $userManager, \BaseFacebook $facebookSdk)
{
$this->userManager = $userManager;
$this->facebookSdk = $facebookSdk;
}
/**
* #see OAuth2\IOAuth2GrantExtension::checkGrantExtension
*/
public function checkGrantExtension(IOAuth2Client $client, array $inputData, array $authHeaders)
{
if (!isset($inputData['facebook_access_token'])) {
return false;
}
$this->facebookSdk->setAccessToken($inputData['facebook_access_token']);
try {
// Try to get the user with the facebook token from Open Graph
$fbData = $this->facebookSdk->api('/me');
if (empty($fbData) || !isset($fbData['id'])) {
return false;
}
// Check if a user match in database with the facebook id
$user = $this->userManager->findUserBy(array(
'facebookId' => $fbData['id']
));
// If no user found, register a new user and grant token
if (null === $user) {
return false;
}
// Else, return the access_token for the user
else {
return array(
'data' => $user
);
}
} catch(\FacebookApiExceptionion $e) {
return false;
}
}
}
And the config.yml :
my.oauth.facebook_extension:
class: My\CoreBundle\Oauth\FacebookGrantExtension
arguments:
userManager: "#fos_user.user_manager"
facebookSdk: "#fos_facebook.api"
tags:
- { name: fos_oauth_server.grant_extension, uri: 'http://grants.api.mywebsite.com/facebook_access_token' }