How to authorize in Skype web SDK - javascript

Recently preview version of new Skype SDK has been released. So I've downloaded samples, read MSDN articles and tried to write simplest JS script to make login to this SDK. So, I've taken code from this MSDN article and slightly modified it(sample code hasn't been working at all - used wrong variable). Modified code works, but returns error:
"TypeError: Cannot read property '1' of null at https://swx.cdn.skype.com/build2015/v5/SDK-build.js:8982:77 at handle (https://swx.cdn.skype.com/build2015/v5/SDK-build.js:2220:63) at https://swx.cdn.skype.com/build2015/v5/SDK-build.js:698:34".
So my code is below:
$(function () {
'use strict'; // create an instance of the Application object;
// note, that different instances of Application may
// represent different users
var Application
var client;
Skype.initialize({
apiKey: 'SWX-BUILD-SDK',
}, function (api) {
Application = api.application;
client = new Application();
// when the user clicks on the "Sign In" button $('#signin').click(function () {
// start signing in
client.signInManager.signIn({
username: 'login',
password: 'pass'
}).then(
//onSuccess callback
function () {
// when the sign in operation succeeds display the user name
alert('Signed in as ' + application.personsAndGroupsManager.mePerson.displayName());
},
//onFailure callback
function (error) {
// if something goes wrong in either of the steps above,
// display the error message
alert(error || 'Cannot sign in');
});
}, function (err) {
alert('some error occurred: ' + err);
});
});
What am I doing wrong?

Finally I've found right answer: for now Skype Web SDK is only for Skype for Business not Skype for consumers. Sad but true.

Related

Azure using wrong callback url during implicit flow login

I'm currently struggling with a weird problem in azure active directory implicit flow oauth authentication. I've implemented a spa webapp using msal.js to login users to their microsoft accont.
The userAgentApplication is executed as shown below:
userAgentApplication = new
Msal.UserAgentApplication(client_id,null,function(errorDes,token,error,tokenType)
{
if(error) {
console.log(JSON.stringify(error));
return;
}
},{ redirectUri: 'https://example.com/app/msalCallback.html' });
When they click login executing the is piece of code:
logInPopup = function() {
var uaa = userAgentApplication;
return new Promise(function(resolve,reject) {
uaa.loginPopup([
'https://graph.microsoft.com/user.read'
]).then(function(token) {
//signin success
console.log(token);
var user = uaa.getUser();
console.log(JSON.stringify(user));
resolve(user);
}, function(error) {
console.log(JSON.stringify(error));
reject(error);
});
})
}
The popup comes up and the user tries to login but the following error comes up:
Microsoft account is experiencing technical problems. Please try again later.
In the url the error parameters string is:
error_description=The provided value for the input parameter
'redirect_uri' is not valid The expected value is
'https://login.live.com/oauth20_desktop.srf' or a URL which matches
the redirect URI registered for this client application.
Upon further research I found that though I configured the redirect uri to be
https://example.com/app/msalCallback.html
(Which I confirmed on the application registration page to be true)
The redirect_uri of the /oauth2/v2.0/authorise url in the login popup page is:
redirect_uri=https://example.com/app/
Which is weird but the above uri is not random one. It is in fact the callback uri for a previous previously registered but now deleted app with the same name.
Further investigation showed that when I config Msal to use the old the redirect_uri login passes.
I'm fresh out of ideas. It looks like a bug in the azure network but wanted to know if anyone else has had this problem or at least point me in the right direction towards getting in contact with azure to find a fix.
Thanks in advance
I've found the cause of the problem after carefully reviewing the msal.js documentation i found that i was setting the redirectUri incorrectly. The correct way is as follows:
var userAgentApplication = new
Msal.UserAgentApplication(client_id,null,function(errorDes,token,error,tokenType)
{
if(error) {
console.log(JSON.stringify(error));
return;
}
});
userAgentApplication.redirectUri = 'https://example.com/app/msalCallback.html'
Hope that helps.
regards

Keycloak JavaScript API to get current logged in user

We plan to use keycloak to secure a bunch of web apps, some written in Java, some in JavaScript (with React).
After the user is logged in by keycloak, each of those web apps needs to retrieve the user that is logged in and the realm/client roles that the user has.
For Java apps, we tried the keycloak Java API (request -> KeycloakSecurityContext -> getIdToken -> getPreferredUsername/getOtherClaims). They seem to work fine
For JavaScript apps, we tried the following code, but could not get Keycloak to init successfully (Note this is in web app code after the user is already authenticated by keycloak, the app is only trying to retrieve who logged in with what roles):
var kc = Keycloak({
url: 'https://135.112.123.194:8666/auth',
realm: 'oneRealm',
clientId: 'main'
});
//this does not work as it can't find the keycloak.json file under WEB-INF
//var kc = Keycloak('./keycloak.json');
kc.init().success(function () {
console.log("kc.idToken.preferred_username: " + kc.idToken.preferred_username);
alert(JSON.stringify(kc.tokenParsed));
var authenticatedUser = kc.idTokenParsed.name;
console.log(authenticatedUser);
}).error(function () {
window.location.reload();
});
I assume it would be fairly common that web apps need to retrieve current user info. Anyone knows why the above code didn't work?
Thanks.
<script src="http://localhost:8080/auth/js/keycloak.js" type="text/javascript"></script>
<script type="text/javascript">
const keycloak = Keycloak({
"realm": "yourRealm",
"auth-server-url": "http://localhost:8080/auth",
"ssl-required": "external",
"resource": "yourRealm/keep it default",
"public-client": true,
"confidential-port": 0,
"url": 'http://localhost:8080/auth',
"clientId": 'yourClientId',
"enable-cors": true
});
const loadData = () => {
console.log(keycloak.subject);
if (keycloak.idToken) {
document.location.href = "?user="+keycloak.idTokenParsed.preferred_username;
console.log('IDToken');
console.log(keycloak.idTokenParsed.preferred_username);
console.log(keycloak.idTokenParsed.email);
console.log(keycloak.idTokenParsed.name);
console.log(keycloak.idTokenParsed.given_name);
console.log(keycloak.idTokenParsed.family_name);
} else {
keycloak.loadUserProfile(function() {
console.log('Account Service');
console.log(keycloak.profile.username);
console.log(keycloak.profile.email);
console.log(keycloak.profile.firstName + ' ' + keycloak.profile.lastName);
console.log(keycloak.profile.firstName);
console.log(keycloak.profile.lastName);
}, function() {
console.log('Failed to retrieve user details. Please enable claims or account role');
});
}
};
const loadFailure = () => {
console.log('Failed to load data. Check console log');
};
const reloadData = () => {
keycloak.updateToken(10)
.success(loadData)
.error(() => {
console.log('Failed to load data. User is logged out.');
});
}
keycloak.init({ onLoad: 'login-required' }).success(reloadData);
</script>
simple javascript client authentication no frameworks.
for people who are still looking...
Your code asks the Keycloak client library to initialize, but it doesn't perform a login of the user or a check if the user is already logged in.
Please see the manual for details: http://www.keycloak.org/docs/latest/securing_apps/index.html#_javascript_adapter
What your probably want to do:
Add check-sso to the init to check if the user is logged in and to retrieve the credentials keycloak.init({ onLoad: 'check-sso' ... }). You might even use login-required.
Make sure that you register a separate client for the front-end. While the Java backend client is of type confidential (or bearer only), the JavaScript client is of type public.
You find a very minimal example here: https://github.com/ahus1/keycloak-dropwizard-integration/blob/master/keycloak-dropwizard-bearer/src/main/resources/assets/ajax/app.js
Alternatively you can register a callback for onAuthSuccess to be notified once the user information has been retrieved.
Once you use Keycloak in the front-end, you will soon want to look in bearer tokens when calling REST resources in the backend.
You might have solved the problem by this time. I hope this answer help rest of the people in trouble.
when you use JavaScript Adopter
Below javascript should be added in of html page.
<script src="http://localhost:8080/auth/js/keycloak.js"></script>
<script>
/* If the keycloak.json file is in a different location you can specify it:
Try adding file to application first, if you fail try the another method mentioned below. Both works perfectly.
var keycloak = Keycloak('http://localhost:8080/myapp/keycloak.json'); */
/* Else you can declare constructor manually */
var keycloak = Keycloak({
url: 'http://localhost:8080/auth',
realm: 'Internal_Projects',
clientId: 'payments'
});
keycloak.init({ onLoad: 'login-required' }).then(function(authenticated) {
alert(authenticated ? 'authenticated' : 'not authenticated');
}).catch(function() {
alert('failed to initialize');
});
function logout() {
//
keycloak.logout('http://auth-server/auth/realms/Internal_Projects/protocol/openid-connect/logout?redirect_uri=encodedRedirectUri')
//alert("Logged Out");
}
</script>
https://www.keycloak.org/docs/latest/securing_apps/index.html#_javascript_adapter Reference Link.
Note : Read the comments for 2 methods of adding json credentials.

Using the Google API javascript in Cordova / Phonegap

I'm developing an application with Cordova and would like to save files in Googe Drive.
I've got success in login to Google, using the cordova-plugin-googleplus (https://github.com/EddyVerbruggen/cordova-plugin-googleplus). However I could not get the plugin returns to me accessToken or idToken so I could use with Google javascript API.
window.plugins.googleplus.login(
{
'scopes': 'https://www.googleapis.com/auth/drive.file profile',
'offline': true,
'webApiKey': ‘CODE’
},
function (obj) {
$scope.$apply(function() {
$scope.srcImage = obj.imageUrl;
$scope.NomeGoogle = obj.displayName;
});
},
function (msg) {
alert('Erro');
alert('error: ' + msg);
}
);
I tried using the code below, but returned me the following error:
"Uncaught gapi.auth2.ExternallyVisibleError: Invalid cookiePolicy"
gapi.load('auth2', function() {
gapi.auth2.init({
client_id: 'REVERSED_CLIENTID',
}).then(function(){
auth2 = gapi.auth2.getAuthInstance();
console.log(auth2.isSignedIn.get()); //now this always returns correctly
});
});
I managed to figure out the problem, why wasn´t getting the serverAuthCode from plugin.
It is necessary to create 2 credentials on the Google Developers Console. The 1st must be Android, this will be for the plugin and the 2nd should be a Web App, this is necessary to achieve serverAuthCode.
The code looks like this
window.plugins.googleplus.login(
{
'scopes': 'https://www.googleapis.com/auth/drive.file profile',
'offline': true,
'webApiKey': ‘REVERSED_CODE of Web App Credential’
},
function (obj) {
$scope.$apply(function() {
$scope.srcImage = obj.imageUrl;
$scope.NomeGoogle = obj.displayName;
});
var data = $.param({
client_id: 'REVERSED_CODE of Web App Credential',
client_secret: 'SECRET_CODE of Web App Credential',
grant_type: 'authorization_code',
code: obj.serverAuthCode
});
var config = {
headers : {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8;'
}
}
$http.post("https://www.googleapis.com/oauth2/v3/token", data, config).success(function(data, status) {
//data.access_token;
/** from now you can do use of google API **/
})
.error(function(data, status) {
console.log(data);
console.log(status);
});
},
function (msg) {
alert('Erro');
alert('error: ' + msg);
}
);
Thank you for your reply rojobo
At first I was hoping to skip the need for cordova-plugin-googleplus and just use the gapi within Cordova/PhoneGap to handle authentication with Google, but it appears the gapi client authentication may not work within cordova's file:// protocol.
The answer from #Joao sent me in the right direction, but I kept getting the Invalid cookiePolicy error when trying to use the gapi after retrieving the access_token (this was because I was ignoring step #2 listed below, and after authenticating with the plugini I was mistakenly trying to authenticate again with the gapi).
There is a step (#3 mentioned below) that was unclear to me. To authenticate with Google and then use the gapi in Cordova/PhoneGap, this worked instead...
use the cordova-plugin-googleplus to take care of the authentication and access token retrieval, do not use the gapi at all here
load the gapi client library (skip over the gapi.client.init() call and all the normal gapi authentication procedures)
Attach the access token we got from the plugin to the gapi client, and then make your gapi calls as needed
Step #3 took some digging for me to find, and meant I needed to add the access_token
gapi.client.setToken({access_token:'abc123456xyz'});
Once the access token was attached to the gapi client, I could use the gapi within Cordova/Phonegap:
// Load the YouTube API.
gapi.client.load('youtube', 'v3', function() {
// Do stuff...
};
try
window.plugins.googleplus.login(
{
'scopes': 'https://www.googleapis.com/auth/drive.file profile',
'offline': true,
'cookiepolicy': 'none',
'webApiKey': ‘CODE’
}

Overriding Email/Username with Cloud Code and PFFacebookUtils

While utilizing the Parse service, I'm trying to allow users to skip sign-in fields by logging into the app via Facebook and using the Facebook information to fill in fields. I'm using Parse's Cloud Code to make the swift client-side code as simple as possible. However, I'm getting a little talk-back from Parse.Cloud when trying to use the cloud code to set the Username and Email Address fields of Parse.User. I get the following errors when running it in-app.
[Error]: Can't modify username in the before save trigger (Code: 141, Version: 1.6.1)
And when removing the username function, I receive:
[Error]: Can't modify email in the before save trigger (Code: 141, Version: 1.6.1)
Through the same code, I'm also setting firstName and lastName without any errors using the same method. Below is the code used.
[CLOUD CODE]
function pad(num, size){ return ('000000000' + num).substr(-size); }
Parse.Cloud.beforeSave(Parse.User, function (request, response) {
var token = request.object.get("authData").facebook.access_token
Parse.Cloud.httpRequest({
url: 'https://graph.facebook.com/v2.1/me?fields=first_name,last_name,email&access_token=' + token,
success: function(httpResponse) {
var responseData = httpResponse.data;
request.object.set("email", responseData.email) // <- Error Occurs Here
request.object.set("username", responseData.email.split("#")[0].concat(".", pad(Math.floor(Math.random()*10000),4))) // <- Error Occurs Here
request.object.set("firstName", responseData.first_name)
request.object.set("lastName", responseData.last_name)
response.success()
},
error: function(){
response.error("Something went wrong.")
}
})
})
[SWIFT CODE]
#IBAction func loginWithFacebookButtonAction(sender: AnyObject){
loginWithFacebookButtonOutlet.setTitle("Logging In...", forState: UIControlState.Normal)
let permissions = ["public_profile", "user_friends", "email"]
PFFacebookUtils.logInWithPermissions(permissions, {
(user: PFUser!, error: NSError!) -> Void in
if user == nil {
println("Uh oh. The user cancelled the Facebook login.")
} else if user.isNew {
println("User signed up and logged in through Facebook!")
self.performSegueWithIdentifier("facebookToApp", sender: self)
} else {
println("User logged in through Facebook!")
self.performSegueWithIdentifier("facebookToApp", sender: self)
}
})
}
Other questions here that I've encountered are caused when the user tries to use .save() instead of response.success() which doesn't seem to be the problem in this situation.
Many thanks.
it seems that username & email can not be altered in beforeSave trigger as they should be unique
Right now, the email field cannot be modified on a beforeSave because this field should be unique. If you were to use a value that another user is already using, this would result in an error that your beforeSave method would not be able to handle.
reference: https://www.parse.com/questions/why-cant-i-modify-the-email-field-in-a-before-save-trigger

Meteor login via Third party library

I'm trying to login to my meteor site via a third party library like this one:
https://gist.github.com/gabrielhpugliese/4188927
In my server.js i have:
Meteor.methods({
facebook_login: function (fbUser, accessToken) {
var options, serviceData, userId;
serviceData = {
id: fbUser.id,
accessToken: accessToken,
email: fbUser.email
};
options = {
profile: {
name: fbUser.name
}
};
userId = Accounts.updateOrCreateUserFromExternalService('facebook', serviceData, options);
return userId;
}, ......
In my client.js I have:
facebookLogin: function () {
if (Meteor.user())
return;
if (!Session.equals("deviceready", true))
return;
if (!Session.equals("meteorLoggingIn", false))
return;
// Do not run if plugin not available
if (typeof window.plugins === 'undefined')
return;
if (typeof window.plugins.facebookConnect === 'undefined')
return;
// After device ready, create a local alias
var facebookConnect = window.plugins.facebookConnect;
console.log('Begin activity');
Session.equals("meteorLoggingIn", true);
Accounts._setLoggingIn(true);
facebookConnect.login({
permissions: ["email", "user_about_me"],
appId: "123456789012345"
}, function (result) {
console.log("FacebookConnect.login:" + JSON.stringify(result));
// Check for cancellation/error
if (result.cancelled || result.error) {
console.log("FacebookConnect.login:failedWithError:" + result.message);
Accounts._setLoggingIn(false);
Session.equals("meteorLoggingIn", false);
return;
}
var access_token = result.accessToken;
Meteor.call('facebook_login', result, access_token, function (error, user) {
Accounts._setLoggingIn(false);
Session.equals("meteorLoggingIn", false);
if (!error) {
var id = Accounts._makeClientLoggedIn(user.id, user.token);
console.log("FacebookConnect.login: Account activated " + JSON.stringify(Meteor.user()));
} else {
// Accounts._makeClientLoggedOut();
}
});
});
}, // login
facebookLogout: function () {
Meteor.logout();
// var facebookConnect = window.plugins.facebookConnect;
// facebookConnect.logout();
},
The third party library (Facebook Android SDK in my case) works fine. My problem is after the "var id = Accounts._makeClientLoggedIn(user.id, user.token);" the Meteor.user() returns Undefined. However If I do a page refresh in the browser works fine and the template renders as a logged in user.
Anyone knows how to fix the 'Undefined' on client ??
PS. On server side the users collection looks fine. The meteor token and everything else are there.
Solved. I had to add : this.setUserId(userId.id);
after userId = Accounts.updateOrCreateUserFromExternalService('facebook', serviceData, options); at server.js
Meteor's client side javascript can't run fibers. Fibers allows synchronous code to be used with javascript since by design js is asynchronous. This means there are callbacks that need to be used to let you know when the task is complete.
From what it looks like Accounts._makeClientLoggedIn doesn't take a callback & unfortunately and doesn't return any data looking at its source. I can't say i've tried this myself because I can't test your code without the android sdk but have you tried using Deps.flush to do a reactive flush?
Also Meteor also has very clean and easy facbeook integration. If you simply add the facebook meteor package
meteor add accounts-facebook
You can get access to a lovely Meteor.loginWithFacebook method that can make everything reactive and your code simpler and really easy. If you need to modify it to use the Android SDK Dialog instead you can easily modify the code out as the code for the module is out there for you to hack up to your spec
Edit: If you're using an external SDK such as the java SDK/cordova plugin
Set your plugin so that it redirects to the following URL (set up for meteor.com hosting):
http://yourmeteorapp.meteor.com/_oauth/facebook?display=touch&scope=your_scope_request_params&state=state&code=yourOAuthCodeFromJava&redirect=YourAPP
So in the querystring we have:
scope= Contains your facebook scope params (for permissions)
code= Your OAuth code from the java sdk
redirect=Where to redirect to after once logged in instead of the window.close
state= A cros site forgery state value, any random value will do
This url is basically used to mimic would what be given to the REDIRECT_URI at : https://developers.facebook.com/docs/reference/dialogs/oauth/
This will redirect to meteor's OAuth helper (at https://github.com/meteor/meteor/blob/master/packages/accounts-oauth-helper/oauth_server.js)
So what would happen is you give the OAuth code from Java to meteor, it fetches the OAuth token and the user's data, then redirect the user to a URL in your app

Categories

Resources