I am successfully authenticating a user to Facebook through my Spotify app, but then I try to request the user information and my .getJSON callback is never called. Here's my code :
auth.authenticateWithFacebook(facebookAppId, facebookPermissions, {
onSuccess: function(accessToken, ttl) {
var request_url = 'https://graph.facebook.com/me';
var url = request_url + '?access_token=' + accessToken;
$.getJSON(url, function(data) {
alert("Working");
});
},
onFailure: function(error) {
console.log("Authentication failed with error: " + error);
},
onComplete: function() { }
});
I tried with $.ajax, adding &callback=?, &callback=myFunction but nothing ever worked... Anyone have an idea of the issue?
Thanks
Make sure you add graph.facebook.com to the RequiredPermissions key in your manifest.json file.
Related
Hi and thanks in advance,
I've successfully setup JWT authentication using django-rest-framework-simplejwt and React but I'm still very confused about the advantages and specifically database hits.
I'm using simplejwt with ROTATE_REFRESH_TOKENS': True 'BLACKLIST_AFTER_ROTATION': True, when my access_token expire I ask for a new one through /api/token/refresh and it blacklist old tokens, I'm using axios interceptors to perform that automatically.
But in my understanding the benefits of JWt is that they are stateless, meaning I don't have to hit the user database table everytime I want to make an a request that needs authentication permission.
The problem is even with a simple view like this :
class IsConnecteddAPI(APIView):
permission_classes = [permissions.IsAuthenticated]
def get(self, request, *args, **kwargs):
data = "You seem to be connected"
return Response(data, status=status.HTTP_200_OK)
using django-silk I see that it still performs 1 query to my user table when I call it with a valid access token, is that normal ? If so why do we say that JWT are stateless ? I'm really confused.
That's my axios code if needed :
import axios from "axios";
const baseURL = "http://localhost:5000";
const axiosInstance = axios.create({
baseURL: baseURL,
timeout: 5000,
headers: {
Authorization: localStorage.getItem("accesstoken")
? "JWT " + localStorage.getItem("accesstoken")
: null,
"Content-Type": "application/json",
accept: "application/json",
},
});
const axioAnonymousInstance = axios.create({
baseURL: baseURL,
timeout: 5000,
headers: {
"Content-Type": "application/json",
accept: "application/json",
},
});
axiosInstance.interceptors.response.use(
(response) => {
return response;
},
async function (error) {
const originalRequest = error.config;
if (typeof error.response === "undefined") {
alert(
"A server/network error occurred. " +
"Looks like CORS might be the problem. " +
"Sorry about this - we will get it fixed shortly."
);
return Promise.reject(error);
}
if (
error.response.status === 401 &&
originalRequest.url === baseURL + "token/refresh/"
) {
window.location.href = "/login/";
return Promise.reject(error);
}
if (
error.response.data.code === "token_not_valid" &&
error.response.status === 401 &&
error.response.statusText === "Unauthorized"
) {
const refreshToken = localStorage.getItem("refreshtoken");
if (refreshToken) {
const tokenParts = JSON.parse(atob(refreshToken.split(".")[1]));
// exp date in token is expressed in seconds, while now() returns milliseconds:
const now = Math.ceil(Date.now() / 1000);
console.log(tokenParts.exp);
if (tokenParts.exp > now) {
return axioAnonymousInstance
.post("/api/token/refresh/", { refresh: refreshToken })
.then((response) => {
localStorage.setItem("accesstoken", response.data.access);
localStorage.setItem("refreshtoken", response.data.refresh);
axiosInstance.defaults.headers["Authorization"] =
"JWT " + response.data.access;
originalRequest.headers["Authorization"] =
"JWT " + response.data.access;
return axiosInstance(originalRequest);
})
.catch((err) => {
// redirect ro /login here if wanted
console.log("axios Safe Instance error");
console.log(err);
// window.location.href = "/login/";
});
} else {
console.log("Refresh token is expired", tokenParts.exp, now);
window.location.href = "/login/";
}
} else {
console.log("Refresh token not available.");
window.location.href = "/login/";
}
}
// specific error handling done elsewhere
return Promise.reject(error);
}
);
export { axiosInstance, axioAnonymousInstance };
( I know I shouldn't use localStorage but whatever )
and I would typically just call this function to make the simple request to the view written above :
const IsConnected = () => {
axiosInstance
.get("/api/is_connected/")
.then((response) => {
if (response.status === 200) {
console.log(response.data);
console.log("Is connected : CONNECTED ");
} else {
console.log("IS connected : not connected");
}
})
.catch((error) => {
console.log("Is connected : NOT CONNECTED");
console.log(error);
});
};
Without the specifics of the exact query hit your db, it's hard to tell what is happening (the db query must have originated from a middleware because there's nothing in your code that does it, and I suspect it's django's CsrfViewMiddleware). However, as for your question of JWT being stateless, I suggest you to take a look at the official introduction.
Basically, what happens with a JWT is that your server performs a signature verification on the token using your server's secret key (please beware of some problems). If the verification passes, then the data stored inside the JWT is trusted and read as is, which is why no database query is necessary. Of course, this does mean that your user will know exactly what is stored inside their token because the data is a simple base64 encoded JSON object.
I am using Skype Web SDK with ionic.
I have two buttons in app after login like "Idle" and "Busy". When I click on it, its changing status of user on Skype for business o365 accordingly.
Now, When I run the app, After login, its work well for first one hour or so and then the app stops reflecting status on Skype For Business.
I get 404 - not found error once it stops updating status.
POST https://webpooldb41e02.infra.lync.com/ucwa/oauth/v1/applications/1145363530/me/reportMyActivity 404 (Not Found)
below is the code I am using for authentication,
let authContext = new Microsoft.ADAL.AuthenticationContext("https://login.windows.net/common");
authContext.acquireTokenSilentAsync("https://graph.windows.net", "Client_id")
.then(function(res) {
console.log(res);
cordova.plugins.backgroundMode.disableWebViewOptimizations();
Skype.initialize({
apiKey: 'Api Key'
}, function (api) {
console.log(new Date().toLocaleString()+" 2");
console.log(api.UIApplicationInstance);
//console.log(this.ucwaData);
window.skypeWebApp = "";
window.skypeWebApp = api.UIApplicationInstance;
window.skypeWebApp.signInManager.signIn({
"client_id": client_id,
"origins": ["https://webdir.online.lync.com/autodiscover/autodiscoverservice.svc/root"],
"cors": true,
"version": 'SkypeOnlinePreviewApp/1.0.0',
"redirect_uri": 'https://login.microsoftonline.com/common/oauth2/nativeclient'
}).then(function () {
console.log(new Date().toLocaleString()+" done");
});
}, function (err) {
console.log(new Date().toLocaleString()+" 3");
console.log(err);
});
}, function () {
cordova.plugins.backgroundMode.disableWebViewOptimizations();
// We require user credentials so triggers authentication dialog
authContext.acquireTokenAsync("https://graph.windows.net", "client_id", "https://login.microsoftonline.com/common/oauth2/nativeclient")
.then(function(res){
if (typeof(document.getElementById("login_with_office")) != 'undefined' && document.getElementById("login_with_office") != null)
{
document.getElementById("login_with_office").innerHTML = "Please wait … Connecting";
}
console.log(res);
//document.getElementById("login_with_office").setAttribute('disabled', 'disabled');
ctrl.loginwitho365();
}, function (err) {
console.log(new Date().toLocaleString()+" Failed to authenticate: " + err);
});
});
And Below is the code I am using for updating status,
window.skypeWebApp.signInManager.state.get().then(function (stat) {
if(stat == "SignedIn")
{
window.skypeWebApp.personsAndGroupsManager.mePerson.status.set(availability);
}
else
{
//Signin COde
}
});
I'm using ember-simple-auth and a custom authenticator for an HTTP basic login with CSRF protection. Everything is working fine except sometimes my restore method resolves when it should be failing, like when the session expires.
When authentication succeeds I resolve with the csrf token, but then when the token or session expires and I refresh the page, the resolve method still succeeds because all I'm doing is checking if the token is still there (not if it's valid). I know this is wrong, so I guess my question would be what is the proper way to handle this? Should I also be resolving with the session id? Should I be sending an AJAX request in the restore method with the stored token to see if it is still valid and returns success? I'm interested in hearing about any other improvements I could make as well.
Here is my authenticator code:
import Ember from 'ember';
import ENV from 'criteria-manager/config/environment';
import Base from 'ember-simple-auth/authenticators/base';
export default Base.extend({
restore(data) {
return new Ember.RSVP.Promise((resolve, reject) => {
if (data.token) {
Ember.$.ajaxSetup({
headers: {
'X-XSRF-TOKEN': data.token
}
});
resolve(data);
}
else {
reject();
}
});
},
authenticate(credentials) {
let csrfToken = this.getCookie('XSRF-TOKEN');
return new Ember.RSVP.Promise((resolve, reject) => {
Ember.$.ajax({
beforeSend: function(xhr) {
xhr.setRequestHeader("Authorization", "Basic " + btoa(credentials.username + ":" + credentials.password));
xhr.setRequestHeader("X-XSRF-TOKEN", csrfToken);
},
url: ENV.host + "/api/users/login",
method: 'POST'
}).done(() => {
//A new CSRF token is issued after login, add it to future AJAX requests
Ember.$.ajaxSetup({
headers: {
'X-XSRF-TOKEN': this.getCookie('XSRF-TOKEN')
}
});
Ember.run(() => {
resolve({
token: this.getCookie('XSRF-TOKEN')
});
});
}).fail((xhr) => {
Ember.run(() => {
if(xhr.status === 0) {
reject("Please check your internet connection!");
}
else if (xhr.status === 401) {
reject("Invalid username and/or password.");
}
else {
reject("Error: Http Status Code " + xhr.status);
}
});
});
});
},
invalidate() {
return new Ember.RSVP.Promise((resolve, reject) => {
let csrfToken = this.getCookie('XSRF-TOKEN');
Ember.$.ajax({
beforeSend: function(xhr) {
xhr.setRequestHeader("X-XSRF-TOKEN", csrfToken);
},
url: ENV.host + '/logout',
method: 'POST'
}).done(() => {
Ember.run(() => {
resolve();
});
}).fail(() => {
Ember.run(() => {
reject();
});
});
});
},
getCookie(name) {
let alLCookies = "; " + document.cookie;
let cookieArray = alLCookies.split("; " + name + "=");
if (cookieArray.length === 2) {
return cookieArray.pop().split(";").shift();
}
}
});
Should I also be resolving with the session id? Should I be sending an
AJAX request in the restore method with the stored token to see if it
is still valid and returns success?
It all depends on your project's needs. In my opinion it's good to check if token is still valid. For example, oauth2-password-grant stores expiring date in session and when restoring simply compares it with current time. You may do this too. Or, if your backend has some token validation endpoint, you may send request to be sure if token is valid.
Am trying to post to facebook wall from an android app written with phonegap. I do get the following error: message:(#200) the user hasn't authorized the application to perform this action type:OAuthException. So my question is How do i get the user to authorize my app so i can post to their wall. I use this code to login:
function login() {
FB.login(
function(response) {
if (response.session) {
alert('logged in');
} else {
alert('not logged in');
}
},
{ perms: 'publish_stream' }
);
}
and i try to post with the below code which throws an error.
function postToWall() {
var body = 'Reading Connect JS documentation';
FB.api('/me/feed', 'post', { body: body }, function(response) {
if (!response || response.error) {
alert('Error occured ' + JSON.stringify(response.error));
} else {
alert('Post ID: ' + response);
}
});
}
Am using the phonegap facebook api from https://github.com/davejohnson/phonegap-plugin-facebook-connect and FB.ui does not work.
Thanks
Posting the same content throws errors so use a text type input for positioning content on Facebook, with post as the text type input:
function postdata()
{
var body = document.getElementById("post").value;
FB.api('/me/feed', 'post', { message: body }, function(response) {
if (!response || response.error)
{
alert('Error occured');
}
else {
alert('Post ID: ' + response.id);
}
});
}
There are serious problems with that phonegap plugin right now. I'm really wishing it would be picked back up to fix them. One of the main issues is that oauth2 isn't supported and the plugin is using an older facebook sdk.
I dont know why but https://graph.facebook.com/132333806850364?access_token=218237124854683|VLsQV-ec2paQpq5hVMFFjtnk9_w returns false even though the app token is valid. The invitation was sent properly and I recieve invitations as well.
//Single user REquest
function sendRequestSingle(c_id,page_id,sendto,from,g_id) {
FB.ui({
method: 'apprequests',
to: sendto,
message: 'Win Mega Prizes!',
title: 'Enter in this contest!',
data: c_id+','+page_id+','+g_id
},
function (response) {
if (response && response.request_ids) {
var requests = response.request_ids;
window.location.href = "http://www.serverhere.com/contest/handle_invitations.php?invitations="+requests+"&contest_id="+c_id+"&page_id="+page_id+"&user="+from+"&g_id="+g_id+"&sendto="+sendto+"&single=1";
} else {
alert('canceled');
}
});
return false;
}