I am working in client side angularjs.I am try to implement google oauth2. I am getting accesstoken but i need to get id_token.
I added app.js , controller.js and html part.
I followed this tutorial: http://anandsekar.github.io/oauth2-with-angularjs/
app.js:
angular
.module('angularoauthexampleApp', [ ])
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.when('/access_token=:accessToken', {
template: '',
controller: function ($location,$rootScope) {
var hash = $location.path().substr(1);
var splitted = hash.split('&');
var params = {};
for (var i = 0; i < splitted.length; i++) {
var param = splitted[i].split('=');
var key = param[0];
var value = param[1];
params[key] = value;
$rootScope.accesstoken=params;
}
$location.path("/about");
}
})
.otherwise({
redirectTo: '/'
});
});
controller.js
angular.module('angularoauthexampleApp')
.controller('MainCtrl', function ($scope) {
$scope.login=function() {
var client_id="your client_id";
var scope="email";
var redirect_uri="http://localhost:9000";
var response_type="token";
var url="https://accounts.google.com/o/oauth2/auth?scope="+scope+"&client_id="+client_id+"&redirect_uri="+redirect_uri+
"&response_type="+response_type;
window.location.replace(url);
};
});
html:
<button class="btn btn-primary" ng-click="login()">Login</button>
You need to use nonce. Add it and id_token will be in response.
For example:
let params = {
'client_id': GOOGLE_API_CLIEND_ID,
'redirect_uri': `${location.origin}/auth/google`,
'response_type': 'id_token token',
'scope': GOOGLE_API_SCOPES,
'state': 'af0ifjsldkj',
'nonce': 'n-0S6_WzA2Mj'
};
For implicit flow nonce param is required. For more information you can check http://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthRequest
To receive an id_token, you need to change your response_type param to:
var response_type="id_token";
as the response you will get an id_token. If you need both - the id_token and access_token, you should add "token" to response_type:
var response_type="token id_token";
To learn more, read OpenId article
Also you could test auth flow using Google Ouath Playground
To trigger an OpenID Connect flow, which is an extension of OAuth 2.0, you need to add the "openid" scope in the authentication request (and urlencode the space in between), so:
var scope="openid%20email";
Related
I'm using ionic to build a mobile app and I'm implementing very lightweight authentication (no security) into the app. Basically when a users hits the login button after submitting their email and password, their information is checked against a database using a POST request. Now my question is, once I have confirmed that the user's information is in the database, I'd like to pass that response object from the POST to a profile page that can then show the user's profile information. How can I pass information (the response object) from one controller to the another page so it can then be displayed on screen? Code below:
app.js
//Login view
.state('signin', {
url: '/signin',
templateUrl: 'templates/signin.html',
controller: 'LoginCtrl'
})
// Profile view:
.state('tab.profile', {
url: '/profile',
views: {
'tab-profile': {
templateUrl: 'templates/tab-profile.html'
controller: 'ProfileCtrl'
}
}
})
controllers.js:
$http.post(url, obj)
.success(function (res, status, headers, config) {
if (res == null){
console.log("bad login");
}
else{
// $scope.response = res;
console.log(res);
console.log("post successful");
$state.go('tab.profile',{response:res});
}
});
tab-profile.html
<ion-view view-title="Profile">
<ion-content>
<ion-list>
<ion-item >{{response.name}}</ion-item>
</ion-list>
</ion-content>
</ion-view>
You can create a service which will store data to be passed to other controllers.
Let me show an example:
var yourApp = angular.module('fooApp', []);
yourApp.factory('yourFactory', function() {
var items = [];
var storeService = {};
storeService.addItem = function(item) {
items.push(item);
};
storeService.removeItem = function(item) {
var index = items.indexOf(item);
items.splice(index, 1);
};
storeService.items = function() {
return items;
};
return storeService;
});
function MyCtrl($scope, yourFactory) {
$scope.newItem = {};
$scope.yourFactory = yourFactory;
}
You can define params in the definiton of a route. Look at the docu (https://github.com/angular-ui/ui-router/wiki/URL-Routing) of the ui-router module to see the right syntax.
In order to pass more complex object between two controllers i would use a service. Xou can set the data in the service after the POST is resolved and after the state change read it in the other controller. Read this link to see examples Passing data between controllers in Angular JS?. Hope this helps :)
I'm new to angular, so I'm pretty sure it is a stupid question, but I failed to figure this out myself.
I have an app in which I have provider to get token from cookies using ngCookies, and I need to access it from inside app.config. I've tried several methods, but all I can get is service code, not a returned variable. What am I doing wrong?
var app = angular.module('appClient', [
'ngCookies'
]);
app.provider('getToken', function getTokenProvider() {
this.$get = ['getTokenService', function(getTokenService, $cookies) {
var token = $cookies.get('token');
return token;
}]
});
app.config(function ($resourceProvider, $httpProvider, getTokenProvider) {
var token = ? //need to get token from getTokenProvider here
$httpProvider.defaults.withCredentials = false;
$resourceProvider.defaults.actions = {
save: { method: 'POST', params: { token: token } },
get: { params: { token: token } },
query: { params: { token: token }, isArray: true }
};
});
Get a tricky solution based on your code. Anyone tell me if this has any side effects or drawbacks.
app.provider('getToken', function getTokenProvider() {
this.$get = ['$cookies', function($cookies) {
//$cookies.put("token","test");
var token = $cookies.get('token');
return token;
}]
});
app.config(function (getTokenProvider,$injectorProvider) {
//instantiate or get the service here
//this should be how angular gets services
//$injectorProvider.$get returns the instance injector (the $injector service)
var token = $injectorProvider.$get().get("getToken");
console.log(token);
});
Here is the plunker
UPDATE:
Using this may cause problem when the there is any code changing the provider of depended services used to instantiate 'getToken'. For example, if you have module.decorate for ngCookies after this config block, it will fail to work.
return {
token: token
};
add this line to return statement in provider and use
getTokenProvider.token
in controller
Maybe my issue seems easy to resolve, but I've this problem since a lot of hours : When I'm in my dashboard, all data of my Firebase database are visible (With Ng-repeat).
But I can't found a solution for choose one specific item and see his details in another page.
I've test this method in HTML (This is an example) :
<div ng-repeat="post in posts">
<div class="card" ng-href="#/post/">">
<h1>{{post.title}}</h1>
<p>{{post.content}}</p>
</div>
</div>
In App JS :
.state('tabpost', {
url: 'tabpost/id',
templateUrl: 'templates/tab-post.html',
controller: 'PostCtrl'
})
In Service JS (in Post Factory) :
myApp.factory("Post", ["$firebaseArray", "$firebaseObject", function($firebaseArray, $firebaseObject) {
var postRef = new Firebase('https://myApp.firebaseio.com/Posts/');
var userRef = new Firebase('https://myApp.firebaseio.com/Users/');
var posts = $firebaseArray(postRef);
var Post = {
all: posts,
get: function (postKey){
var postId = $firebaseObject(postRef);
return $firebaseObject(eventRef.child('Posts').child(postId).child(userid));
}
,
add: function (post){
var postId = $firebaseArray(postRef, userRef);
event.userid = userRef.getAuth();
return postId.$add(post);
}
}
return Post;
}]);
My PostCtrl :
myApp.controller('PostCtrl', ['$ionicFrostedDelegate', '$ionicScrollDelegate','$state','$scope', 'Post', 'Auth', '$firebaseObject', '$firebaseArray', function($ionicFrostedDelegate, $ionicScrollDelegate, $state,$scope, Post, Auth, $firebaseObject, $firebaseArray) {
var PostRef = new Firebase("https://myApp.firebaseio.com/Posts");
$scope.posts = Post.all;
$scope.post = {'title': '', 'content': ''};
$scope.auth = Auth;
PS : It took 16 hours to try a bunch of tutorials mostly obsolete , and I am sure that the solution can not be that simple.
I already posted two similar issues yesterday and this morning but each of the proposed solutions have not worked . I would be immensely grateful to the person who would help me out of this impasse .
I still have a little trouble with jsFiddle promised I would learn to use it once I would have solved this problem.
Thank you for giving me time
Can you please try the following set of codes, I've explained the changes in comments in Controller and added :id in App JS
In App JS :
.state('tabpost', {
url: 'tabpost/:id',
templateUrl: 'templates/tab-post.html',
controller: 'PostCtrl'
})
PostCtrl :
myApp.controller('PostCtrl', ['$ionicFrostedDelegate', '$ionicScrollDelegate','$state','$scope', 'Post', 'Auth', '$firebaseObject', '$firebaseArray', '$routeParams', function($ionicFrostedDelegate, $ionicScrollDelegate, $state,$scope, Post, Auth, $firebaseObject, $firebaseArray, $routeParams) {
var PostRef = new Firebase("https://myApp.firebaseio.com/Posts");
var id = $routeParams.id; //get the id from url, $routeParams is injected in controller
$scope.posts = Post.get(id); //call get() method of Post with the id retrieved
$scope.post = {'title': '', 'content': ''};
$scope.auth = Auth;
you can use route provider to do that. I used that for my application and it works great.
myApp.config( ['$routeProvider', function($routeProvider){
$routeProvider.
when('tabpost', {
templateUrl: 'tabpost/id',
controller: 'PostCtrl'
});
}]);
I'm new to Angular and i'm currently trying to get the id of a project from the url and pass it as a var inside a service.
My current code is as follows:
app.config(
['$routeProvider',
function($routeProvider) {
...
$routeProvider.when('/project/:ProjectId', {
templateUrl: 'project.html',
controller: 'ProjectController',
activePage: 'Portfolio'
});
...
}
])
...
.controller('ProjectController', function($scope, ProjectFactory) {
$scope.content = ProjectFactory.async();
})
...
.factory('ProjectFactory', function($http) {
var factoryProject = {
async: function(page) {
var projectID = 'XXXXXX';
var apiKey = 'XXXXXX';
var url = 'http://behance.net/v2/projects/' + projectId + '?api_key=' +
apiKey + '&callback=JSON_CALLBACK';
var promise = $http.jsonp(url).error(function(response, status) {
alert(status);
}).success(function(response, status) {
console.log(response.project);
}).then(function(response, status) {
return response.data;
});
return promise;
}
};
return factoryProject;
});
I know i'm missing something, how can i store :ProjectId, from $routeProvider, in the variable projectID?
Thanks!
A couple things missing here to get this to work. The first is in your 'ProjectController', you need to inject the $routeParams variable making the controller definition
.controller('ProjectController', function($scope, ProjectFactory, $routeParams) {
$scope.content = ProjectFactory.async();
})
Now you can access ProjectId in the $routeParams object
var pid = $routeParams.ProjectId
Now you can pass the pid as a param into the factory
ProjectFactory.async(pid)
I haven't tested this yet, but I think that's all you're missing.
You need to inject the $routParams service into your factory and access it like so:
var projectId = $routeParams.ProjectId;
Inject $routeParams object to the controller, and use $routeParams.ProjectId
More info here: https://docs.angularjs.org/api/ngRoute/service/$route
Lets say i list all users in a list, when i click a user i want to route to a new view and get the data for the selected person.
What is the preferred way? Should i move the data i already got when i listed the users or should i create a new server call?
My first thought is to pass the data, but the problem with this is that the data the gets lost if the user refreshes the page.
What is the best practice to solve this?
Small example:
(function() {
var app = angular.module('app');
var controllerId = 'app.controllers.views.userList';
app.controller(controllerId, [
'$scope', 'UserService',function ($scope, userService) {
var vm = this;
vm.users = [];
userService.getAllUsers().success(function (data) {
vm.users= data.users;
});
var gotoUser = function(user) {
// Pass the user to UserDetail view.
}
}
]);
})();
<div data-ng-repeat="user in vm.users" ng-click="vm.gotoUser(user)">
<span>{{customer.firstname}} {{customer.lastname}}</span>
</div>
i now list the user details in UserDetail view, this view is now vulnerable against a browser refresh.
Typically most people just create a new server call, but I'll assume you're worried about performance. In this case you could create a service that provides the data and caches it in local storage.
On controller load, the controller can fetch the data from the service given the route params and then load the content. This will achieve both the effect of working on page refresh, and not needing an extra network request
Here's a simple example from one of my apps, error handling left out for simplicity, so use with caution
angular.
module('alienstreamApp')
.service('api', ['$http', '$q','$window', function($http, $q, $window) {
//meta data request functions
this.trending = function() {
}
this.request = function(url,params) {
var differed = $q.defer();
var storage = $window.localStorage;
var value = JSON.parse(storage.getItem(url+params))
if(value) {
differed.resolve(value);
} else {
$http.get("http://api.alienstream.com/"+url+"/?"+params)
.success(function(result){
differed.resolve(result);
storage.setItem(url+params,JSON.stringify(result))
})
}
return differed.promise;
}
}]);
I would say that you should start off simple and do a new server call when you hit the new route. My experience is that this simplifies development and you can put your effort on optimizing performance (or user experience...) where you will need it the most.
Something like this:
angular.module('app', ['ngRoute', 'ngResource'])
.factory('Users', function ($resource) {
return $resource('/api/Users/:userid', { userid: '#id' }, {
query: { method: 'GET', params: { userid: '' }, isArray: true }
});
});
.controller("UsersController",
['$scope', 'Users',
function ($scope, Users) {
$scope.loading = true;
$scope.users = Users.query(function () {
$scope.loading = false;
});
}]);
.controller("UserController",
['$scope', '$routeParams', 'Users',
function ($scope, $routeParams, Users) {
$scope.loading = true;
$scope.user = Users.get({ userid: $routeParams.userid }, function () {
$scope.loading = false;
});
$scope.submit = function () {
$scope.user.$update(function () {
alert("Saved ok!");
});
}
}]);
.config(
['$routeProvider', '$locationProvider',
function ($routeProvider, $locationProvider) {
$routeProvider
.when('/users', {
templateUrl: '/users.html',
controller: 'UsersController'
})
.when('/users/:userid', {
templateUrl: '/user.html',
controller: 'UserController'
})
.otherwise({ redirectTo: '/users' });
}
]
);