angular http: how to call images with custom headers? - javascript

In the html view, images are displayed like this:
<img ng-src="{{element.image.url}}">
element.image.url points to an url like: /rest_api/img/12345678.
This is working fine, images are displayed.
Now, I add authentication:
Before the user is authenticated, every resources respond with an http error 401, images too. When authentication succeeds, a token is placed in a custom headers and sent with every $http requests, allowing access the resources:
$http.defaults.headers.common['Authorization'] = token;
This is working fine for Json files loaded with $resource. But the direct links to the images are still 401 after authentication.
How to call the images with custom headers?
Or any advice on how I should do this.

As said here you can use angular-img-http-src (bower install --save angular-img-http-src if you use Bower).
If you look at the code, it uses URL.createObjectURL and URL.revokeObjectURL which are still draft on 19 April 2016. So look if your browser supports it.
In order to use it, declare 'angular.img' as a dependency to your app module (angular.module('myapp', [..., 'angular.img'])), and then in your HTML you can use http-src attribute for <img> tag.
In your example it would be: <img http-src="{{element.image.url}}">
Of course, this implies that you have declared an interceptor using $httpProvider.interceptors.push to add your custom header or that you've set statically your header for every requests using $http.defaults.headers.common.MyHeader = 'some value';

There is a vary simple answer for that. You should use: angular-img-http-src.
Problem:
You used token based auth and you need to serve images from secured
routes.
Solution:
Use http-src instead of ng-src and it will fetch images using the
$http service - meaning Authorization headers added via interceptors
will be present - then build a Blob and set the src to an objectURL.
It works perfectly on my project.

I am facing the same problem.
The best solution I found is passing the Authorization token as a query parameter.
For example :
<img src="http://myhost.com/image/path?accessToken=123456789" >
This way you can secure those images only for your REST consumers.

Consider the URL be http://foo.com/bar.png
In your controller,
angular.module('foo')
.controller('fooCtrl', ['$sce',
function($sce) {
$scope.dataSrc = "http://foo.com/bar.png"
$scope.src = $sce.trustAsResourceUrl($scope.dataSrc)
}
])
And in your view,
<img ng-src="{{src}}" />
.. seems to do the trick.

As far as I know it's not possible to pass additional headers with asset requests (scripts, images, media, CSS files that the browser loads while rendering the page). That's all controlled by the browser. Only when making a XHR (AJAX) request can you modify headers.
I would suggest looking at your server side authentication and seeing if there's a solution there.

Related

Include header when chunks are fetched with code splitting

I've used code splitting to seprate restricted parts of my app into different chunks. This is working great so far, now I would like to ensure that the files themselves don't get served unless authenticated. I was thinking of using ngx_http_auth_request_module
http://nginx.org/en/docs/http/ngx_http_auth_request_module.html#auth_request
Which allows to send a sub-request before serving certain files. How can I ensure that certain headers are always send as part of the HTTP request when React wants to fetch the necessary chunks?
I have trouble understanding why you would need to prevent unauthenticated malicious users to have access to your static chunks.
Dynamic imports and code splitting are mainly used to reduce the bundle size for large applications as users won't necessarily need everything.
In order to secure your app you need to prevent users from seeing or tampering with data they do not have access to. This means the security lies with the API your app is talking to.
What I do:
Reject unauthenticated requests to the API
Keep a token client-side on authentication
Pass and check the token on all requests
Burn the token when obsolete and redirect to login
Notify, redirect users when they do not have access to some data or better not displaying content they do not have access to
I'm sure you already did what I wrote above, what I want to emphasize is that chunks are basically empty UI filled with data from the secured API.
Let's say I have bad intentions and I bypass client-side routing in order to have access to the restricted chunk. It will be an empty UI with secured API routes, I won't be able to do anything with it.
In case you have a very specific need, you might need to write a webpack plugin.
about the ensure request
One of webpack 's properties is that it can fetch only necessary chunks when loading pages.You can just use like require.ensurn to query chunks when necessary,so there is no need to ensure the certain headers.
ngx_http_auth_request_module
Ngx_http_auth_request_module and sub-request are always used to fetch web file in server.It's always used as backend authentication module.Here is the data flow direction in nginx.
When you download file, the download request will be passed to the server, then server return the override Http Request to Nginx,then Nginx will find the exact file.
The ngx_http_auth_request_module allows to send request to back server(like php .tomcat), and based on the request to pass or not, if pass, you will be able to fetch file in the back server.
nginx-----load speed
The nginx always fetch static file, like index.html.If have to validate the permission for every js/css everytime,then fetch it throw,thd loading speed for page will be very slow.
about how to authenticate
Since you have separated app.Here is a little suggestions.You can get the authenticated request by only import restricted parts in the authenticated file.And the webpack will automatically handle the rest.
fetch data from the server in the non-restricted part with information to authenticate like this:
http://.../api/auth?info=...
based on the infos in server to authenticate, and pass other infos like type back to the frontend
based on the type information to view .
if (this.props.type === "restrict"){
<restrict component/>
} else {
<non-restrict component/>
}

Nextjs global api calls

I am developing react based web application using NEXT.js,. As specified in NEXT.js, documentation to fetch the data before page loads, i am putting required action dispatch code in getInitialProps of the specific page. but some data fetching calls(action dispatch) like fetching authenticated user's data will be common to all the pages, so is there any way to dispatch such actions from single place before page load.
Thanks!
update, now you can use getServerSideProps and nextjs provides an easy way to get user cookie : How to use cookie inside `getServerSideProps` method in Next.js?
--------- old answer ---------
simple answer: use cookie, code refer https://github.com/nextjs-boilerplate/next.js-boilerplate https://github.com/nextjs-boilerplate/next-fetch
-- details --
I had the same question when I first adopt next.js, as it worked in react, people prefer use a token to tag authed user and fetch always run in front-end. But as next.js made ssr a build in feature, I tried and find auth by cookie is possible, and I start https://github.com/nextjs-boilerplate/next.js-boilerplate and split out a fetch based on cookie https://github.com/nextjs-boilerplate/next-fetch
-- how it works --
1.client side fetch: use fetch option option.credentials = 'include' and option.headers.Cookie=document.cookie will patch cookie into your request. Bnd when fetch back result, this become wired, you cannot access cookie header, so you have to use another header and additional logic needed in backend logic like res.header('custom-set-cookie', res.getHeader('set-cookie'))
2.server side fetch: first you need the express request object, and get cookie like req.headers.cookie, then pack it into fetch request option. when fetch back, get cookie like r.headers._headers[cookieHeaderName] and pack into response res.header('set-cookie', setCookie)
then after you pack this transfer up, you can simply call a json api and cookie will automatically transfered. And if you don't need to change cookie through header (you can through js), you can ommit the extra handle like res.header('custom-set-cookie', res.getHeader('set-cookie')) in api
you can try my ssr login here http://nextjs.i18ntech.com/login

AngularJS: Retrieving Videogular templates stored in $templateCache results 404 Error

I currently develop an AngularJS 1.5.9 Single Page Application on my localhost with NodeJS running backend, where I use
Videogular framework. http://www.videogular.com/
Everything is fine except inserting videogular object on my page. I strictly follow the given example: http://www.videogular.com/examples/simplest-videogular-player/
<videogular vg-theme="controller.config.theme.url">
<vg-media vg-src="controller.config.sources"
vg-tracks="controller.config.tracks"
vg-native-controls="true">
</vg-media>
</videogular>
But it results in AngularJS error:
(sessionId in the request is the auth token not linked to current problem)
I have found the following in videogular.js :
$templateCache.put("vg-templates/vg-media-video", "<video></video>");
$templateCache.put("vg-templates/vg-media-audio", "<audio></audio>");
I have tried to store files locally, and the error disappeared
Actually there are a lot of plugins for Videogular and they all are using $templateCache to store some files in the cache, so it would be very confusing to manually store them locally in my app folder.
How can such files be stored in the cache using $templateCache so they can be extracted properly?
I apreciate your help.
UPDATE
I have tried insert $templateCache.get to directive, where the part is loading with error 404, and it works. But still doesn't work as it supposed to be.
It seems like there is an issue with sessionId that you pass in URL parametrs, do you actually need it?
I guess your interceptor or whatever auth managing module is wrong configured, so you don't check request target URL and id parameters are going to be added for local calls as well as for backend calls.

using mjpeg with basic authentication in cordovaapp

To get a motionjpeg stream from a ip camerIn a native App I would add a RequestHeader to the GET-Request containing the credentials. In an ajax-call I also can append headers to get a single image.
But to show continuous images the only way seem to be using
<img src="url_to_mpjeg">
The webui of the camera is successfully doing the GET-call like this:
1. you enter the ui with a request to index.html, which needs credentials
2. any further request (like the GET request) automatically have the basic authentication injected by the browser
So I also tried calling another URL of the camera with authentication-header in advanced but this doesn't work in cordova. Every single request needs a manual authentication in the header, nothing is magically added to the headerfields.
I think the reason why it automatically works in the camera webui is because the cameras index.html and further requests are all from the same origin, but in my cordovaapp, the UI is coming from file://local somewhere.
Is there a way in javascript to call a jpeg stream with basic authentication?
As stated by the chromium team, images credentials does not work anymore
If you want to load some stream as mjpg or img with basic auth protected url use iframe instead.
<iframe src="you_stream_link"></iframe>

Get an access token without being connected to facebook

I need to retrieve a facebook page's list of posts (feed) using their javascript SDK, just like they explain in their docs: https://developers.facebook.com/docs/graph-api/reference/v2.4/page/feed
/* make the API call */
FB.api(
"/{page-id}/posts",
function (response) {
if (response && !response.error) {
/* handle the result */
}
}
);
I need it to be my website's "news section", so users should see it even if they are not connected to facebook.
The problem
Cool, but there is a problem... It returns: An access token is required to request this resource.
Holy cow... I'd like to get some access token for you #facebook, but my app doesn't make use of your authentication tools/plugins.
ANYWAY, I tried with FB.getLoginStatus(); but doesn't work, because the only way it can return an access_token is if the user is actually connected to the application. My users may not even be logged to facebook!
So, ¿How can I get an access_token to be stored into a variable, and later be used to get /{my-page}/posts?
I've already payed a look to this SO question, but it doesn't solves my problem, simply because there are no such "generic tokens".
I've also read https://developers.facebook.com/docs/facebook-login/access-tokens/ and that also relies on tokens generated through facebook login methods... So, can't I display a list of fb page's posts in my website, without being connected into facebook, hence an application?
ADD: My app is build with angularJS, I'm not dealing with server-side code. I shall rely purely on javascript methods.
You could either use an page or an app access token, but as you'd be using them on the client-side, neither of them are an option.
See
https://developers.facebook.com/docs/facebook-login/access-tokens#apptokens
https://developers.facebook.com/docs/facebook-login/access-tokens#pagetokens
Note that because this request uses your app secret, it must never be made in client-side code or in an app binary that could be decompiled. It is important that your app secret is never shared with anyone. Therefore, this API call should only be made using server-side code.
I'd strongly recommend to build a simple server-side script (PHP for example) to proxy the request to the Graph API. You could then call this via AJAX for example and load the posts asynchronously (and alse get rid of the FB JS SDK!). There is NO way to handle this in a secure manner if you don't want to use FB Login for all of your users (which also doesn't make much sense IMHO).
I think it's straightforward :)
Since pages' posts are always public, it only needs a valid access token to retrieve page posts.
Quoting what you've written:
So, ¿How can I get an access_token to be stored into a variable, and later be used to get /{my-page}/posts?
You only require an access token.
My suggestion would be;
- Generate an access token for yourself (no extra permission needed)
- request page-id/posts
This way you don't require other users to be connected to facebook, you can simply requests page-id/posts to retrieve posts with access token you generated for yourself.
I hope it solves your problem :D
TIP: As long as posts are public, you only require a valid access token, it doesn't need to be user or page specific.

Categories