implement wechat authentication in cordova hybrid app ios - angularjs

I am developing a cordova hybrid app targeting ios & need to add authentication via wechat in login page.
$scope.wechatLogin=function(){
scope = "snsapi_userinfo",state = "_" + (+new Date());
Wechat.auth(scope, state, function (response) {
alert(JSON.stringify(response));
$.get('https://api.weixin.qq.com/sns/oauth2/access_token?myappid=' + appId + '&secret=' + myappSecret + '&code=' + response.code + '&grant_type=authorization_code', function (accessTokenResponse) {
alert(JSON.stringify(accessTokenResponse));
// you should save access token response somewhere, e.g. cookies, local storage, etc.
var accessToken = accessTokenResponse.access_token;
var openId = accessTokenResponse.openid;
// get user information
$.get('https://api.weixin.qq.com/sns/userinfo?access_token=' + accessToken + '&openid=' + openId + '&lang=zh_CN', function (userInfoResponse) {
console.log(userInfoResponse);
});
});
});
}
when testing this in device, it opens wechat & gives a message as "oops! Something went wrong". Can You help me to resolve this.
Thank you very much!

Related

Calling API from JavaScript Frontend: 401 unauthorized using angularfire

I am following this tutorial on adding firebase authentication to my webapp using endpoints v2 (migrated from v1 yesterday).
I previously had google accounts authentication only but want to switch to firebase for adding e.g. facebook.
When I call my API from my JavaScript Frontend (built with angularJS & angularfire) I get a 401 unauthorized.
I feel, I am missing a logical step:
I can log-in on the client-side (pop-up opens and my facebook-name is displayed).
Missing step?
endpoints.get_current_user() does not get a user.
Where am I going wrong?
This is what I want to initialize the page where I want to get a profile from the backend:
`/**
* Initialize profile page.
* Update the profile if the user's profile has been stored.
*/
$scope.init = function () {
var retrieveProfileCallback = function () {
$scope.profile = {};
$scope.loading = true;
gapi.client.myapi.getProfile().execute(function (resp) {
$scope.$apply(function () {
$scope.loading = false;
if (resp.error) {
// Failed to get a user profile.
} else {
// Succeeded to get the user profile.
$scope.profile.displayName = resp.result.displayName;
$scope.profile.someOtherProperty = resp.result.someOtherProperty;
$scope.initialProfile = resp.result;
}
});
}
);
};
if (!firebaseUser) {
//TODO
} else {
retrieveProfileCallback();
}
};`
This is the start of the method that is ultimatively called from getProfile()-endpoint:
def _getProfileFromUser(self):
"""Return user Profile from datastore, creating new one if non-existent."""
## Make sure user is authed
user = endpoints.get_current_user()
if not user:
raise endpoints.UnauthorizedException('Authorization required')
Here is my API decorator (openapi.json has been deployed):
# - - - - firebase - - - - - - - - - - - - - - - - - -
firebase_issuer = endpoints.Issuer(
issuer='https://securetoken.google.com/appname-123456',
jwks_uri='https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken#system.gserviceaccount.com')
# - - - - Endpoints API - - - - - - - - - - - - - - - - - - -
#endpoints.api(name='myapi',
version='v1',
scopes=[EMAIL_SCOPE],
issuers={'firebase': firebase_issuer})
class MyApi(remote.Service):
I feel like I am massively misinterpreting the tutorials. It seems too easy and does not work.
E.g. for the google accounts authorization I initialized the oauth2 api like so in the index.html:
`<script>
function init() {
gapi.client.load('myapi', 'v1', null, '//' + window.location.host + '/_ah/api');
gapi.client.load('oauth2', 'v2', function () {
angular.bootstrap(document, ['conferenceApp']);
});
};
</script>`
I took that out because I figured I am switiching to firebase.
Like so:
`<script>
/**
* Initializes the Google API JavaScript client. Bootstrap the angular module after loading the Google libraries
* so that Google JavaScript library ready in the angular modules.
*/
function init() {
gapi.client.load('myapi', 'v1', null, '//' + window.location.host + '/_ah/api', function () {
angular.bootstrap(document, ['myApp']);
});
};
</script>`
The openapi configuration looks fine. The problem is with the client code, which handles sign-in flow to get a Firebase auth token. You need to use Firebase web SDK instead of Google JS SDK. You can take a look at the instructions at https://firebase.google.com/docs/auth/web/google-signin.

integrating linkedin login with angularjs application

I am new to angular js .I would like to know the procedure to get api key and integrating linked in sign in ,sign up with angularjs application.
You can use LinkedIn SDK to handle authorisation and sing up or sing off users.
Documentation: https://developer.linkedin.com/docs/getting-started-js-sdk
You have to initial SDK. You will need to create an app in your LinkedIn Developer panel. Then you get an API Key there.
Then in your app you have to create a service that will call LinkedIn API.
Something like this:
export class LinkedIn {
constructor($q, $window) {
'ngInject';
this.$q = $q;
this.$window = $window;
};
get() {
let doc = this.$window.document;
let script = doc.createElement('script');
let deferred = this.$q.defer();
script.src = 'http://platform.linkedin.com/in.js';
script.innerHTML = [
'api_key: ' + YOUR_API_KEY,
'authorize: ' + 'true',
'lang: ' + 'en-US',
'onLoad: onLinkedInApiLoad',
'scope: ' + YOUR_APP_SCOPE
].join('\n');
this.$window.onLinkedInApiLoad = () => {
deferred.resolve(this.$window.IN);
};
doc.body.appendChild(script);
return deferred.promise;
};
}
Next you need to decide where and when you want to initial this call. You can do that in .run block or made some middleware to handle it. After that you will receive LinkedIn API object.
When you have got your LinkedIn API object you can request authorisation, check if user has been already logged in and etc. Options are describe in documentation. You can authorise user calling IN.User.authorize(handler || angular.noop) or logout IN.User.logout(handler || angular.noop)
There is also options to do a callback on Event where user log in or log out for example:
IN.Event.on(IN, eventName, callback, callbackScope, extraData);
IN.Event.onOnce(IN, eventName, callback, callbackScope, extraData);
You can use angular module for linkedIn authentication. angular-social-login

angular link requires basic auth

I have a links within my app to documents like http://site/mydoc.pdf where the site requires basic auth to open. I've tried attaching auth in my my app like
.config(function($httpProvider) {
var auth = "user:pass";
$httpProvider.defaults.headers.common['Authorization'] = 'Basic ' + auth;
})
But when clicking on the link, i'm still getting the popup for credentials to continue to the document.

How to open a redirect link in my app without redirecting to external link?

I have the following code (AJS + Cordova):
$scope.update = function () {
myService.update()
.then(function (response) {
$scope.result = response.data;//prints [Object object]
console.log("Success!..." + response.data + "result.." + $scope.result);
angular.forEach($scope.result, function(value, key){
console.log(key + ': ' + value); //prints success:true
// $location.url(""+urlToGo);
$window.location.href = urlToGo;
})
},
function (error) {
$scope.status = 'Unable toget resposne ' + error;
});
};
Here, $window.location.href = urlToGo; will open a new window in mobile browser, which means user will leave my app. So, is there any technique, I can handle it inside my app using Angular or Cordova, without showing browser to him?
The following Link helped me resolve this issue for my Cordova App.
Phonegap - How to open external link inside the app
Briefly from that post:
var onInApp = window.open('http://paymentpage.com', '_blank', 'location=no,hidden=yes,closebuttoncaption=Done,toolbar=no');
I did have to play with the settings dependant upon the platform to get the correct result.
The latest Cordova Docs explain it much better :
https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-inappbrowser/index.html
Hopefully this will point you in the correct direction.

Cordova InAppBrowser show location bar Cordova AngularJS Oauth

Hi I'm using the Cordova InAppBrowser and AngularJS Oauth plugins.
When I press a normal link button like this:
<a class="external" ng-href="https://www.website.com/" targe="_blank" >open link</a>
In combination with this:
<script>
$( document ).ready(function() {
// open links in native browser (phonegap);
$(document).on('click', '.external', function (event) {
event.preventDefault();
window.open($(this).attr('href'), '_blank');
return false;
});
});
</script>
It opens the link in the in app browser. In the InAppBrowser when loading the url it is showing the url location at the bottom. So this is working OK.
When the AngularJS Oauth plugin opens the InAppBrowser and starts to load the login page of Facebook for example it doesn't show the loading url location at the bottom.
I tried to add "location=yes" in the Oauth plugin like this, but it is still not showing the url loading bar at the bottom:
window.open('https://www.website.com/oauth/authorize?client_id=' + clientId + '&redirect_uri=http://localhost/callback&scope=' + appScope.join(",") + '&response_type=code&approval_prompt=force', '_blank', 'location=yes,clearsessioncache=yes,clearcache=yes');
How can I force to show the loading bar with Oauth in the InAppBrowser ?
The reason I want this is when a login page needs some time to load there is no loading indication and you mind think there is nothing happening.
This is how the Oauth function looks like with location=yes:
strava: function(clientId, clientSecret, appScope) {
var deferred = $q.defer();
if(window.cordova) {
var cordovaMetadata = cordova.require("cordova/plugin_list").metadata;
if(cordovaMetadata.hasOwnProperty("cordova-plugin-inappbrowser") === true || cordovaMetadata.hasOwnProperty("org.apache.cordova.inappbrowser") === true) {
var browserRef = window.open('https://www.strava.com/oauth/authorize?client_id=' + clientId + '&redirect_uri=http://localhost/callback&scope=' + appScope.join(",") + '&response_type=code&approval_prompt=force', '_blank', 'location=yes,clearsessioncache=yes,clearcache=yes');
browserRef.addEventListener('loadstart', function(event) {
if((event.url).indexOf("http://localhost") === 0) {
requestToken = (event.url).split("code=")[1];
$http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
$http({method: "post", url: "https://www.strava.com/oauth/token", data: "client_id=" + clientId + "&client_secret=" + clientSecret + "&code=" + requestToken })
.success(function(data) {
deferred.resolve(data);
})
.error(function(data, status) {
deferred.reject("Problem authenticating");
})
.finally(function() {
setTimeout(function() {
browserRef.close();
}, 10);
});
}
});
browserRef.addEventListener('exit', function(event) {
deferred.reject("The sign in flow was canceled");
});
} else {
deferred.reject("Could not find InAppBrowser plugin");
}
} else {
deferred.reject("Cannot authenticate via a web browser");
}
return deferred.promise;
},
I found the solution.
My app was loading the oauth plugin twice, once via a separate oauth script I added to my project and once via the ngCordova library. The ngCordova script was overruling the oauth script I added so that's why the location=yes was not working.
I removed the separate oauth script and changed location=no to yes in the ngCordova oauth script.

Resources