Capability token is not valid or missing Twilio - jwt

I have integrated Twilio Programmable Voice. Now I am trying to make client to call from browser and also receive calls to browser using Twilio JS Client. When I try to make the call it says.
message: "Capability token is not valid or missing."
I have searched the internet and Twilio documentation as well but nothing is helping me. Here is my code.
View
<button onclick="callCustomer('{{ '+xxxxxxxx' }}')" type="button" class="btn btn-primary btn-lg call-customer-button">
Call customer
</button>
Controller
public function newToken(Request $request) {
// Required for all Twilio access tokens
$twilioAccountSid = 'ACxxxxxxxxx';
$twilioApiKey = 'SKxxxxxxxxxxx';
$twilioApiSecret = 'xxxxxx';
$outgoingApplicationSid = 'APxxxxxxxxxxx';
$identity = "Jhon_Doe";
$token = new AccessToken(
$twilioAccountSid, $twilioApiKey, $twilioApiSecret, 3600, $identity
);
$voiceGrant = new VoiceGrant();
$voiceGrant->setOutgoingApplicationSid($outgoingApplicationSid);
$voiceGrant->setIncomingAllow(true);
$token->addGrant($voiceGrant);
return $token->toJWT();
}
JS
function callCustomer(phoneNumber) {
$.get("/token", {forPage: window.location.pathname}, function (data) {
console.log(data);
const device = new Twilio.Device();
device.setup(data);
var params = {"phoneNumber": phoneNumber};
device.connect(params);
});
}
I have tried to debug my token from jwt.io debug tool and it says:
Invalid Signature.
I am sure that I am missing something but can't figure it out what. Any help or tip will be appreciated.

I have figured it out just posting answer for future reference. The issue was of twilio js version. I had included the older version which was causing the issue. The lates version to this date is Version: 1.13. Capability token is deprecated in this version and uses Access Token now.

Related

conv.askToDeepLink is not a function

The old way of invoke the askToDeepLink are no more working in DialogFlow even in V1.
app.askToDeepLink('Great! Looks like we can do that in the Android app.', 'tool for Android',
'sample://scheduleMeeting', 'com.sample', 'handle this for you');
Anybody know the way to invoke askToDeepLink in V2?
If you are trying to connect one of your Android apps with your Assistant app, you should try this.
app.intent('ask_to_deep_link_detail', (conv) => {
const options = {
destination: 'Google',
url: 'example://gizmos',
package: 'com.example.gizmos',
reason: 'handle this for you',
};
conv.ask('Great! looks like maybe we can do that in the app.');
conv.ask(new DeepLink(options));
});
Getting the results of the helper
If the user accepts the link, the dialog with your app will end and you will not receive further requests. If they reject the link, you will receive another request with the intent actions.intent.LINK and a status argument:
app.intent('ask_to_deep_link_confirmation', (conv, params, response) => {
conv.ask('Okay maybe we can take care of that another time.');
});
I hope this helps.

How do I prevent the user from being asked to grant permissions for a Google Apps Marketplace app that the domain administrator has approved

I've been trying to convert an old style Marketplace app to the new way of doing things, but I keep having the user prompted for authorization when they first follow the Universal Navigation link (the app was installed onto the domain via the 'Test Install Flow' link on the marketplace SDK).
When I request the 'openid email' scopes, the prompt appears, but if I specify a separate scope (instead of, not in addition to 'openid email') that is part of the app, it doesn't prompt the user for auth (unless I request offline access, which I want for parity of features with the previous version, but one problem at a time...).
Sample code using the google api nodejs client:
var http = require('http');
var googleapis = require('googleapis');
var url_parse = require('url');
var OAuth = googleapis.auth.OAuth2;
var client = new OAuth(
CLIENT_ID
CLIENT_SECRET
REDIRECT_URL
);
http.createServer(dispatcher).listen(80);
function dispatcher(req, res){
res.writeHead(200, {'Content-Type': 'text/html'});
var url = url_parse.parse(req.url, true);
if(url.pathname === '/auth') {
auth_time(res);
} else if (url.pathname === '/callback') {
console.log('looking good');
client.getToken(url.query.code, function(err, tokens){
console.log(tokens);
client.setCredentials(tokens);
res.end(render_page('yep'));
});
} else {
res.end(render_page('different page'));
console.log(req.url);
}
}
function auth_time(res){
res.end(render_page('<a href="'+client.generateAuthUrl({
scope: 'openid email https://www.google.com/m8/feeds', //Prompts
// scope: 'https://www.google.com/m8/feeds', //Doesn't prompt
include_granted_scopes: 'true',
access_type: 'online'
})+'">Click for auth</a>'));
}
function render_page(contents){
return '<html><head><title>The page</title></head><body>'+contents+'</body></html>';
}
This similar question has an answer suggesting that https://www.googleapis.com/auth/plus.me is added to the list of scopes used on the Marketplace SDK, but that scope is removed on page refresh (I'm guessing it is treated as identical to one or both of https://www.googleapis.com/auth/userinfo.email & https://www.googleapis.com/auth/userinfo.profile which are automatically set as scopes and are not removable.

Error 500 backendError with Gmail API and Google APIs Node Client

I'm trying to use the new Gmail API with the Google API Node client. I created a new project from the developer console, set up a new "Service Account" Client ID, and enabled access to the API.
As a proof of concept, I am simply trying to list the threads in my inbox. When I enable the OAuth 2.0 toggle for the API explorer and enter my email address, the request succeeds and I see a JSON response with data.
Now I try to do the same in Node:
var googleapis = require('googleapis');
var SERVICE_ACCOUNT_EMAIL = '...SNIP...';
// generated by: openssl pkcs12 -in ...SNIP...p12 -out key.pem -nocerts -nodes
var SERVICE_ACCOUNT_KEY_FILE = 'key.pem';
var jwt = new googleapis.auth.JWT(
SERVICE_ACCOUNT_EMAIL,
SERVICE_ACCOUNT_KEY_FILE,
null,
['https://www.googleapis.com/auth/gmail.readonly']);
googleapis
.discover('gmail', 'v1')
.execute(function(err, client) {
jwt.authorize(function(err, result) {
if(err) console.error(err);
else console.log(result);
client.gmail.users.threads.list()
.withAuthClient(jwt)
.execute(function(err, result) {
if(err) console.error(err);
else console.log(result);
});
});
});
First I print the results of the authorize() call, which looks like it returns a token, so I think I have all the OAuth stuff setup properly:
{ access_token: '...SNIP...',
token_type: 'Bearer',
expires_in: 1404277946,
refresh_token: 'jwt-placeholder' }
Then I try to actually use the API, but I get an error:
{ errors:
[ { domain: 'global',
reason: 'backendError',
message: 'Backend Error' } ],
code: 500,
message: 'Backend Error' }
At this point, I don't know what else to try. I think the OAuth stuff is working properly, because I haven't gotten any authentication errors. I also think the API itself is working and my account is fine, because I can use it through the API Explorer. I don't see any indication that the Node library is at fault either. In short, I have no idea what the problem is. Any ideas?
You are using the Service Account to authenticate your requests to GMail. Your Service Account will not have a Gmail as far as I know, only users have GMail. For this reason you will need to do the OAuth2 flow with the user (see here for example).

Facebook Auth with AngularJS and Django REST Framework

I am developing a SPA application with AngularJS which uses Django backend for the server. The way that I communicate with the server from the SPA is with django-rest-framework. So now I want to make authentication with facebook (google and twitter too) and I read a lot on this topic and found OAuth.io which is making the authetication on the client SPA side and python-social-auth which is doing the same thing but on the server side.
So currently I have only the client auth, my app is connecting to facebook (with OAuth.io) and login successfully. This process is returning access_token and then I am making a request to my API which have to login this user or create account for this user by given token and this part is not working. So I am not sure where I am wrong, maybe because there isn't a full tutorial about using python-social-auth so maybe I am missing something or.. I don't know..
So some code of this what I have:
On the SPA side: This is the connection with OAuth.io and is working because I am getting the access token. Then I have to make a request to my rest API. backend is 'facebook', 'google' or 'twitter'
OAuth.initialize('my-auth-code-for-oauthio');
OAuth.popup(backend, function(error, result) {
//handle error with error
//use result.access_token in your API request
var token = 'Token ' + result.access_token;
var loginPromise = $http({
method:'POST',
url: 'api-token/login/' + backend + '/',
headers: {'Authorization': token}});
loginPromise.success(function () {
console.log('Succeess');
});
loginPromise.error(function (result) {
console.log('error');
});
});
On the server in my settings.py I have added social plugin to the installed apps, template context preprocessors, some auth backends and that is my file:
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
...,
'rest_framework',
'rest_framework.authtoken',
'api',
'social.apps.django_app.default',
'social'
)
TEMPLATE_CONTEXT_PROCESSORS = ("django.contrib.auth.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.static",
"django.core.context_processors.request",
"django.contrib.messages.context_processors.messages",
'social.apps.django_app.context_processors.backends',
'social.apps.django_app.context_processors.login_redirect',)
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
)
}
SOCIAL_AUTH_FACEBOOK_KEY = 'key'
SOCIAL_AUTH_FACEBOOK_SECRET = 'secret'
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']
AUTHENTICATION_BACKENDS = (
'social.backends.open_id.OpenIdAuth',
'social.backends.facebook.FacebookOAuth2',
'social.backends.facebook.FacebookAppOAuth',
'social.backends.google.GoogleOpenId',
'social.backends.google.GoogleOAuth2',
'social.backends.google.GoogleOAuth',
'social.backends.twitter.TwitterOAuth',
'django.contrib.auth.backends.ModelBackend',
)
In my views.py of the API I have the following (I found it here):
from django.contrib.auth.models import User, Group
from rest_framework import viewsets, generics
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import authentication, permissions, parsers, renderers
from rest_framework.authtoken.serializers import AuthTokenSerializer
from rest_framework.decorators import api_view, throttle_classes
from social.apps.django_app.utils import strategy
from rest_framework.permissions import IsAuthenticated, IsAuthenticatedOrReadOnly
from django.contrib.auth import get_user_model
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token
class ObtainAuthToken(APIView):
throttle_classes = ()
permission_classes = ()
parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
renderer_classes = (renderers.JSONRenderer,)
serializer_class = AuthTokenSerializer
model = Token
# Accept backend as a parameter and 'auth' for a login / pass
def post(self, request, backend):
serializer = self.serializer_class(data=request.DATA)
if backend == 'auth':
if serializer.is_valid():
token, created = Token.objects.get_or_create(user=serializer.object['user'])
return Response({'token': token.key})
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
# Here we call PSA to authenticate like we would if we used PSA on server side.
user = register_by_access_token(request, backend)
# If user is active we get or create the REST token and send it back with user data
if user and user.is_active:
token, created = Token.objects.get_or_create(user=user)
return Response({'id': user.id , 'name': user.username, 'userRole': 'user','token': token.key})
#strategy()
def register_by_access_token(request, backend):
backend = request.strategy.backend
user = request.user
user = backend._do_auth(
access_token=request.GET.get('access_token'),
user=user.is_authenticated() and user or None
)
return user
And finally I have these routes in urls.py:
...
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
url(r'^api-token-auth/', 'rest_framework.authtoken.views.obtain_auth_token'),
url(r'^api-token/login/(?P<backend>[^/]+)/$', views.ObtainAuthToken.as_view()),
url(r'^register/(?P<backend>[^/]+)/', views.register_by_access_token),
...
Everytime when I try to do auth, OAuth.io is working and the rqest to api returns
detail: "Invalid token"
I think that I missed something in the configuration of python-social-auth or I am doing everything wrong. So I will be glad if anyone has some ideas and want to help :)
Add the following line to your ObtainAuthToken class
authentication_classes = ()
and your error {"detail": "Invalid token"} will go away.
Here's why...
Your request contains the following header
Authorization: Token yourAccessToken
yet you have defined rest_framework.authentication.TokenAuthentication in DEFAULT_AUTHENTICATION_CLASSES.
Based on this Django thinks you want to perform token authentication as you have passed a Token in. It fails because this is an access token for facebook and doesn't exist in your django *_token database, hence the invalid token error. In your case all you need to do is tell Django not to use TokenAuthentication for this view.
FYI
Keep in mind you may encounter further errors as your code execution was halted before the post method of ObtainAuthToken executed. Personally when trying to step through your code I got the error
'DjangoStrategy' object has no attribute 'backend'
on
backend = request.strategy.backend
and resolved it by changing to
uri = ''
strategy = load_strategy(request)
backend = load_backend(strategy, backend, uri)
Additionally you should update your you register_by_access_token function as it doesn't line up with the working code from the blog you referenced. The blog author posted his latest code here. Your version doesn't pull the token out of the auth header which is required if you want to use it to auth with a third party like facebook.
Yea. Solved. The settings are not right and you need to add permissions.
REST_FRAMEWORK = {
# Use hyperlinked styles by default.
# Only used if the `serializer_class` attribute is not set on a view.
'DEFAULT_MODEL_SERIALIZER_CLASS':
'rest_framework.serializers.HyperlinkedModelSerializer',
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
]
}
and some info about pipeline:
SOCIAL_AUTH_PIPELINE = (
'social.pipeline.social_auth.social_details',
'social.pipeline.social_auth.social_uid',
'social.pipeline.social_auth.auth_allowed',
'social.pipeline.social_auth.social_user',
'social.pipeline.user.get_username',
'social.pipeline.social_auth.associate_by_email',
'social.pipeline.user.create_user',
'social.pipeline.social_auth.associate_user',
'social.pipeline.social_auth.load_extra_data',
'social.pipeline.user.user_details'
)
I'm using tools just like you, but I provide my login/register/.... with
django-allauth package, and then use django-rest-auth for API handling.
You just need follow the installation instruction, then use them for your rest APIs.
Adding allauth and rest-auth to your INSTALLED_APPS:
INSTALLED_APPS = (
...,
'rest_framework',
'rest_framework.authtoken',
'rest_auth'
...,
'allauth',
'allauth.account',
'rest_auth.registration',
...,
'allauth.socialaccount',
'allauth.socialaccount.providers.facebook',
)
Then add your custom urls:
urlpatterns = patterns('',
...,
(r'^auth/', include('rest_auth.urls')),
(r'^auth/registration/', include('rest_auth.registration.urls'))
)
Finally, add this line:
TEMPLATE_CONTEXT_PROCESSORS = (
...,
'allauth.account.context_processors.account',
'allauth.socialaccount.context_processors.socialaccount',
...
)
These two packages works like a charm, and you don't need to have concern about any type of login.registration, because allauth package handles both django model login and oAuth login.
I hope it helps

Facebook Login and Iframe redirection

I am building an Facebook IFrame App. I am using the below javascript code to request user to login and allow permissions for the application, after which they are supposed to be redirected to the iframe app. The code works correctly. But, I have two issues with it.
a. as soon as the app loads in IFrame, it redirects to a page (http://www.facebook.com/connect/uiserver.php?app_id=......) and displays a large facebook icon. When I click this icon it redirects to facebook login page. I want my app to redirect to the login page directly instead of showing the inbetween facebook icon page.
b. When the user clicks 'Allow' button for the requested permission in facebook, the page redirects to my main site (http://www.mysite.com) instead of the iframe application(http://apps.facebook.com/myapp).
I have pasted my javascript below, this works with above quirks.
var api_key = 'xxxxxxxxxxxxxxx';
var channel_path = 'xd_receiver.htm';
FB_RequireFeatures(["Api"], function () {
FB.Facebook.init(api_key, channel_path);
var api = FB.Facebook.apiClient;
// require user to login
api.requireLogin(function (exception) {
FB.Connect.showPermissionDialog("publish_stream");
});
});
Help much appreciated.
I have remembered something!
You must use target="_top" in all your links and redirections in a iframe application!
Hope I help you.
Thanks for your answers.
I used the solution posted by McKAMEY(Facebook API: FB.Connect.requireSession issues) with few changes, and it works as intended, without showing the intermediate facebook icon page, and also it redirects after authentication to the iframe app correctly.
I have posted below the working solution in case someone needs it.
var api_key = 'xxxxxxxxxxxx';
var channel_path = './xd_receiver.htm';
var canvas_url = "http://apps.facebook.com/myappxxxx/"// ensure your canvasurl has a '/' at the end!
function Initialize() {
FB_RequireFeatures(["Api"], function () {
FB.Facebook.init(api_key, channel_path);
FB.ensureInit(function () {
FB.Connect.ifUserConnected(
function () {
var uid = FB.Connect.get_loggedInUser();
if (!uid) {
authRedirect();
return;
}
},
authRedirect);
});
});
}
function authRedirect() {
//This is the Sample URL Structure for redirecting to facebook
//http://www.facebook.com/connect/uiserver.php?
//app_id=XXXXXXXXXXXXX&
//next=xxxxxxxxxx_success_url_here_XXXXXXX&
//display=page&
//perms=XXXXXX_comma_seperated_permissions_list_hereXXXXXX&
//fbconnect=1&
//method=permissions.request
window.top.location.href = "http://www.facebook.com/connect/uiserver.php?app_id=" + encodeURIComponent(api_key) + "&next=" + encodeURIComponent(canvas_url) + "&display=page&perms=publish_stream&fbconnect=1&method=permissions.request";
}
Initialize();
Note on redirecting within a frame to the Facebook login page. You have to use javascript to redirect the entire page since the login page passed the X-Frame-Options:DENY header and modern browsers will prevent you from sending the user to the URL if that header is present. Solution is to use javascript::window.top.location = ''; to redirect the whole page
I'm not sure on the middle page between redirection but what does your apps canvas and connect url point to?
The redirection after login should go to that page unless you have this overridden somewhere in your code.
Change the urls in the settings on fb to apps.facebook.com/myapp if that's not what its set to.
You may use the new Facebook Graph API (http://developers.facebook.com/docs/api) to handle authentication. First, you must check if you have the access_token:
$access_token = $_REQUEST['access_token'];
if($access_token != NULL) {
...
}
else {
// the following javascript
}
And the javascript is:
<script type="text/javascript">
top.location.href = '<?= "https://graph.facebook.com/oauth/authorize?client_id=".$appid."&redirect_uri=".$appurl."oauth_redirect" ?>'
</script>
You must have a file oauth_redirect.php like this:
<?php
$code=$_REQUEST['code'];
$url = "http://graph.facebook.com/oauth/access_token?client_id=".$appid."&redirect_uri=".$appurl."oauth_redirect&client_secret=".$appsecret."&code=$code";
$curl = curl_init();
// SET URL FOR THE POST FORM LOGIN
curl_setopt($curl, CURLOPT_URL,$url);
curl_setopt($curl, CUPROPT_SSL_VERIFYPEER, true);
curl_setopt($curl, CUPROPT_SSL_VERIFYHOST, true);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION ,1);
curl_setopt($curl, CURLOPT_HEADER ,0);
curl_setopt($curl, CURLOPT_RETURNTRANSFER ,1);
// EXECUTE 1st REQUEST (LOGIN)
$response = curl_exec ($curl);
?>
<script type="text/javascript">
top.location.href = '<?= $appurl."?".$response ?>';
</script>
Finally, you can return to your index page (the $appurl variable) and test if the user has permission testing access_token presence.
Hope it helps!