I try to implement Auth0 in my Single-Page-App using angular.
here are the scripts i loaded for auth0:
<!-- Auth0's lock widget library -->
<script type="text/javascript" src="https://cdn.auth0.com/js/lock-9.0.js"></script>
<!-- Angular cookie wrapper library for client cookies -->
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-cookies.js"></script>
<!-- Auth0's Angular SDK Library -->
<script type="text/javascript" src="https://cdn.auth0.com/w2/auth0-angular-4.js"></script>
<!-- Angular wrapper for localStorage and sessionStorage. Defaults to ng-cookies if not available -->
<script src="http://cdn.rawgit.com/auth0/angular-storage/master/dist/angular-storage.js" type="text/javascript"> </script>
<!-- Angular wrapper library for JWT-->
<script src="http://cdn.rawgit.com/auth0/angular-jwt/master/dist/angular-jwt.js" type="text/javascript"> </script>
But the Token has an invalid Signature and is always unauthorized when i try the api call for the user information here : Api to get user data
the token is stored in the local storage in the following eventhandler
authProvider.on('loginSuccess', ['$location', 'profilePromise', 'idToken', 'store',
function($location, profilePromise, idToken, store) {
profilePromise.then(function(profile) {
store.set('user', profile.email);
store.set('token', idToken);
});
$location.path('/');
}]);
The debugger from jwt.io always says invalid Signature when i try to decode my jwt even with my client secret.
Did i do something wrong ? Why is my token Signature invalid ? Why is my token unauthorized? Does the Api page even work on actual data ?
EDIT:
I found out that i used the wrong api call i used the one for auth0-access-tokens instead for JWTs.
But still the JWT Debugger shows invalid Signature
If you are using the idToken, you should be calling the /tokeninfo endpoint. Be sure to follow the required format: it should be a POST, with content type json containing this payload:
{
"id_token" : "[the token]"
}
However, you probably don't want to do any of this. The call to /tokeninfo will get you the user profile, but the SDK already does that for you after authenticating the user. The same user profile is available in the callback from profilePromise here:
authProvider.on('loginSuccess', ['$location', 'profilePromise', 'idToken', 'store',
function($location, profilePromise, idToken, store) {
profilePromise.then(function(profile) {
// 'profile' contains the same information that
// you would get calling '/tokeinfo' or '/userinfo'
// so consider storing the whole 'profile' instead
// of just 'profile.email'
store.set('user', profile.email);
store.set('token', idToken);
});
$location.path('/');
}]);
Related
I am very new to angularJS. I am searching for accessing services from RESTful API, but I didn't get any idea. How can I do that?
Option 1: $http service
AngularJS provides the $http service that does exactly what you want: Sending AJAX requests to web services and receiving data from them, using JSON (which is perfectly for talking to REST services).
To give an example (taken from the AngularJS documentation and slightly adapted):
$http({ method: 'GET', url: '/foo' }).
success(function (data, status, headers, config) {
// ...
}).
error(function (data, status, headers, config) {
// ...
});
Option 2: $resource service
Please note that there is also another service in AngularJS, the $resource service which provides access to REST services in a more high-level fashion (example again taken from AngularJS documentation):
var Users = $resource('/user/:userId', { userId: '#id' });
var user = Users.get({ userId: 123 }, function () {
user.abc = true;
user.$save();
});
Option 3: Restangular
Moreover, there are also third-party solutions, such as Restangular. See its documentation on how to use it. Basically, it's way more declarative and abstracts more of the details away from you.
The $http service can be used for general purpose AJAX. If you have a proper RESTful API, you should take a look at ngResource.
You might also take a look at Restangular, which is a third party library to handle REST APIs easy.
Welcome to the wonderful world of Angular !!
I am very new to angularJS. I am searching for accessing services from RESTful API but I didn't get any idea. please help me to do that. Thank you
There are two (very big) hurdles to writing your first Angular scripts, if you're currently using 'GET' services.
First, your services must implement the "Access-Control-Allow-Origin" property, otherwise the services will work a treat when called from, say, a web browser, but fail miserably when called from Angular.
So, you'll need to add a few lines to your web.config file:
<configuration>
...
<system.webServer>
<httpErrors errorMode="Detailed"/>
<validation validateIntegratedModeConfiguration="false"/>
<!-- We need the following 6 lines, to let AngularJS call our REST web services -->
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*"/>
<add name="Access-Control-Allow-Headers" value="Content-Type"/>
</customHeaders>
</httpProtocol>
</system.webServer>
...
</configuration>
Next, you need to add a little bit of code to your HTML file, to force Angular to call 'GET' web services:
// Make sure AngularJS calls our WCF Service as a "GET", rather than as an "OPTION"
var myApp = angular.module('myApp', []);
myApp.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}]);
Once you have these fixes in place, actually calling a RESTful API is really straightforward.
function YourAngularController($scope, $http)
{
$http.get('http://www.iNorthwind.com/Service1.svc/getAllCustomers')
.success(function (data) {
//
// Do something with the data !
//
});
}
You can find a really clear walkthrough of these steps on this webpage:
Using Angular, with JSON data
Good luck !
Mike
Just to expand on $http (shortcut methods) here: http://docs.angularjs.org/api/ng.$http
//Snippet from the page
$http.get('/someUrl').success(successCallback);
$http.post('/someUrl', data).success(successCallback);
//available shortcut methods
$http.get
$http.head
$http.post
$http.put
$http.delete
$http.jsonp
For instance your json looks like this :
{"id":1,"content":"Hello, World!"}
You can access this thru angularjs like so:
angular.module('app', [])
.controller('myApp', function($scope, $http) {
$http.get('http://yourapp/api').
then(function(response) {
$scope.datafromapi = response.data;
});
});
Then on your html you would do it like this:
<!doctype html>
<html ng-app="myApp">
<head>
<title>Hello AngularJS</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
<script src="hello.js"></script>
</head>
<body>
<div ng-controller="myApp">
<p>The ID is {{datafromapi.id}}</p>
<p>The content is {{datafromapi.content}}</p>
</div>
</body>
</html>
This calls the CDN for angularjs in case you don't want to download them.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
<script src="hello.js"></script>
Hope this helps.
I am using identity server 4 with the oidc-client library in an angular 2 web page. The login, logout calls and api calls are all working correctly without any issues. I have recently started trying to get the token auto refresh functionality to work in the web page also. I see that web page defined in silent-redirect is getting created in the iFrame and I see calls to the id4 service but always get a timeout error on the iframe and no new token received.
Any help or suggestions on what I am missing or doing wrong would be greatly appreciated. I have included relevant client side code below.
I do see the token expiring event being triggered.
thanks a lot in advance.
angular2 service
import { UserManager, Log, MetadataService, User, WebStorageStateStore } from 'oidc-client';
export const settings: any = {
authority: 'http://10.3.30.215:8885',
client_id: 'tps',
redirect_uri: 'http://10.3.30.215:4201/auth.html',
response_type: 'id_token token',
automaticSilentRenew: true,
monitorSession: true,
scope: 'openid scope1 scope2 offline_access',
post_logout_redirect_uri: 'http://10.3.30.215:4201',
silent_redirect_uri: 'http://10.3.30.215:4201/silent_renew.html',
loadUserInfo: true
};
public mgr: UserManager = new UserManager(settings);
constructor(private http: Http) {
Log.logger = console;
Log.level = Log.DEBUG;
}
login() {
this.mgr.clearStaleState().then(() => {
this.mgr.signinRedirect();
});
}
silent_renew.html:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<script src="oidc-client.js"></script>
<script>
new Oidc.UserManager().signinSilentCallback();
</script>
</body>
</html>
Assuming your site is secure with https and you own the frontend, you could possibly do a resource owner password grant implementation with refresh tokens and use angular's built in auth features.
This site has some good info on how to implement an http interceptor. https://ryanchenkie.com/angular-authentication-using-the-http-client-and-http-interceptors.
Your use case might not allow this approach, but it is an option. Hope that helps.
I'm trying to create an app that will retrieve the stock name, asking and buy price from Yahoo Finance API, using Restangular. I'm having a problem with accessing a public API in the local application I'm creating when I do a GET request. This is the URL with parameters that I'm sending:
http://finance.yahoo.com/d/quotes.csv?s=MSFT+GE&f=nab
Using Postman, this get request returns an array which contains the stock name, asking price and buy price of the stock. Doing the request in postman returns the desired information without any errors.
When I do this request in my local, I get the following error:
XMLHttpRequest cannot load http://finance.yahoo.com/d/quotes.csv?s=MSFT+GE&f=nab. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access.
The HTML code is as follows:
<html ng-app="app">
<head>
<title>Restangular</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="//code.angularjs.org/1.2.27/angular-resource.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
<script src="//cdn.rawgit.com/mgonto/restangular/master/dist/restangular.min.js"></script>
</head>
<body>
<div ng-controller="IndexCtrl" ng-cloak>
<ul>
<li ng-repeat="person in people">{{person.Name}}</li>
</ul>
</div>
And the JS:
var app = angular.module('app', ['restangular'])
.config(function(RestangularProvider) {
RestangularProvider.setBaseUrl('http://finance.yahoo.com/d');
});
app.controller('IndexCtrl', function($scope, Restangular) {
$scope.people = Restangular.all('quotes.csv?s=MSFT+GE&f=nab').getList();
});
I'm confused by this error because since this is a public API and POSTMAN can access it, I'd assume that the header is already present in the API server. Why would I get this error when requesting from my local?
Any help would be GREATLY appreciated.
Here's me making a JSONP request which fails because it's trying to receive a CSV file. I don't think restangular knows how to read CSV files either which is what you are attempting. I think you need to do the same thing as you are now but using the YQL API instead because I don't think this is going to work.
Anyway here's the code:
http://plnkr.co/edit/GokYqzJ0dXw86C6AM2UP?p=preview
The request (which goes through but fails due to the file type):
app.controller('MainCtrl', function($scope, $http) {
$scope.name = 'World';
$http.jsonp('http://finance.yahoo.com/d/quotes.csv', {
params: {
callback: 'JSON_CALLBACK',
s: 'MSFT GE',
f: 'nab'
}
}).success(function(response) {
console.log(response);
}).catch(function(response) {
console.log(response);
})
});
I just built a simple application calling a rest api built with symfony and secured with fos_oauth.
I have a AuthService that return an access token that allow my mobile application to access to my api.
It is stored in local storage :
On my browser using ionic serve (similar to phonegap serve) the application is perfectly working and i can access to my variable stored locally. When emulating with ios, it is perfectly working. But when emulating with android or displaying my app on my phone with phonegap app. I can't access to those variables. Does that sound normal to you?
[phonegap] 404 http://ynd.dev/api/login?access_token=undefined
index.html :
<!-- Utils -->
<script src="js/service/LocalStorageService.js"></script>
<!-- JS Config -->
<script src="js/functions.js"></script>
<script src="js/config/parameters.js"></script>
<!-- your app's js -->
<script src="js/app.js"></script>
<script src="js/config/routing.js"></script>
<script src="js/service/AuthService.js"></script>
LocalStorageService.js :
setObject: function(key, value) {
$window.localStorage.setItem(key, JSON.stringify(value));
},
getObject: function(key) {
return JSON.parse($window.localStorage.getItem(key) || '{}');
}
parameters.js :
// Resources
var domain = 'http://ynd.dev';
var public_id = '4_4spkzm1pubcw40og04okk4wogs0cc44wkgkkoco88k8cwgkwgs';
var secret = '28es09ymlcg0wgskgs4cso0co0ok0ww0gw8g0k8g4kcowckcco';
// Access token
var access_token = '';
var identity_token = '';
app.js :
var app = angular.module('ionicApp', ['ionic', 'ionic.utils', 'ngResource']);
app.run(function($ionicPlatform,$rootScope, $localStorage, $location, AuthService) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if(window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if(window.StatusBar) {
StatusBar.styleDefault();
}
access_token = $localStorage.getObject('access_token');
identity_token = $localStorage.getObject('identity_token');
AuthService.token();
});
$rootScope.$on('$stateChangeStart', function (event, next) {
access_token = $localStorage.getObject('access_token');
identity_token = $localStorage.getObject('identity_token');
AuthService.token();
// IF no user logged
if(isObjectEmpty(identity_token)){
$location.path( "/login" );
}
});
});
AuthService:
This is how the object is stored in local.
$localStorage.setObject('access_token', {
key: res.data.access_token,
type: 'anonymous',
expires_at: Date.now()+(res.data.expires_in*1000)
});
Any ideas or hints?
UPDATE : (CORS)
allow_origin: ['*']
allow_headers: ['*']
allow_methods: ['POST', 'PUT', 'GET', 'DELETE', 'OPTIONS']
When using the app within Phonegap the application is called from the file system, thus runs on the file:// protocol. When you wan to call your server, you will need to use JSONP or CORS headers on your server to make a successful connection, as otherwise cross-domain security policies will arise.
It was simply not working because the emulated application does not access the localhost.
First solution :
Call the api from an online host.
Second solution :
Instead of calling http://localhost/ Call the IP (You can get it with a ifconfig, for myself i used ifconfig vboxnet0).
For vitual host i have not figure it out.
This is how I am handling the process of sendig the csrf_token().
In the <head> section I added the token as a constant.
<script type="text/javascript">
var myApp = angular.module('myApp', ['ngRoute', 'ngSanitize', 'productController', 'productService'])
.constant("CSRF_TOKEN", '<?= csrf_token() ?>');
</script>
In the productService when I send post data, I include the following:
headers: {'Content-Type': 'multipart/x-www-form-urlencoded', 'X-XSRF-TOKEN': CSRF_TOKEN}
Then I receive from Laravel the error:
DecryptException: invalid data
If I remove X-XSRF-TOKEN from headers: above, then I receive the TokenMismatchException.
As suggested from another post, I encrypted the csrf_token(), since Laravel is expecting the token to be encrypted, but even then I still receive DecryptException: invalid data.
Changing X-XSRF-TOKEN to X-CSRF-TOKEN solved the problem.
When testing, I had to destroy the cookie and restart the browser for the token to kick in.
change XSRF to CSRF and restart your browser.