I'm trying to think on approach to do authentication with Angular and remote server. Usually what I do in local server, like what they did in MEAN.IO, check if has user and if it is I put it on the global window and that's how I know that user is authenticated.
for example in laravel:
#if(Auth::check())
<script>
var user= [[[Auth::user()]]]
</script>
#endif
and it survive refresh because im check it at run time too.
but now the server is remotely and i have to do something like get request to some url /getUser. But thats not good since all the AngularJS
components will have to wait for the response to return causing inconsistencies and
development overhead.
So what I should do?
You can use "resolve" in order to avoid changing your current logic.
Define a Security service that performs the check let's say Security.getUser() and add it to the resolve of each route you need to secure. That way, your controller will be loaded only once the user is already checked. In case the server will return an authentication error, redirect to the login screen.
You can check out my slides from a secured angular talk I gave goo.gl/kMvoFj
or go over my github repository (It's still very raw, but the main idea is there) ng-secure, I think it might help you.
Related
With browser's devtools ability to reload edited javascript overrides, how can you "securely" execute validation-dependent front-end code?
Say you want to conditionally display some sort of proprietary UI element(s) (humor me) dependent on an authorized users permissions. The authorized user data would be validated with a promise, but if the conditional is client side based on the returned promise data, couldn't someone just remove that conditional, save as an override and reload the page?
if (permissionGroup == 'Team'){
return <>{children}</>
}
if (nodeENV !== 'development'){
checkAuth();
}
Edit and run JS override to return children without running auth checks
if (permissionGroup !== 'anything'){
return <>{children}</>
}
Any way to prevent this? Am I mis-informed about devtools security? or is the industry-standard understood that, other than data, anything client side is essentially open source?
The answer is, it is simply not possible to securely control dynamically rendered components on the front end, outside of using possibly some sort of encryption service like JSscrambler
The solution is, only render components to the client side, to user that are authorized to access or view the components, who has been authenticated, validated and authorized on the server.
You never ever trust the client, as you mentioned the client can modify the code and override your "security features".
You will need a backend and need to validate the clients input.
I've read quite a lot of documentation about Webpush, and so far I've understood that push subscription should have a read-only propery expirationTime. Also, I understand how should I react if the browser decides that subscription is outdated (handle event in service worker, etc.). But is it possible to somehow set expiration date manually, without implementing complex client side logic? I guess that this is an ordinary problem for apps that have authentification.
My problem is that if user gets logged out automatically, webpush endpoint stays valid. I know multiple ways this can be solved with workarounds, but I guess that's not the optimal way for a relatively basic problem.
It's been a long time ago that I've fixed this, but I guess sharing my solution can be helpful.
The solution was to make a HTTP request from service worker to the app using fetch('/path') , because all cookies from the app are also attached to requests made from SW.
So, if user is not logged in, you are redirected to login page.
My code:
fetch('/path', {method: 'GET', redirect:'error'}).then(function(result) {
... //some code specific for my app
}).catch(function(e) {
registration.unregister(); //error on redirect to login
});
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.
I'm in a dead end, because I know that Javascript isn't made for synchronous work, and specially not AngularJS. However, I am in a situation where I am stuck needing it.
I have one main page on the domain "www" (with AngularJS), that calls "api" a lot. Some of the resources on "api" requires authentication, so it returns an 401, which in turn AngularJS picks up and displays a login-box when it sees.
The www-login supports a bunch of login methods and sends the password/oauth/whatever to the "api", which returns a token which the angular app stores in a cookie, and sets in $http.defaults.headers.common['Authorization'] so it can be used to authenticate furter requests to the api.
The same method is also used to get the username that belongs to the api-token.
This works perfectly and solves my design goals. But if the browser is going to an url that requires authentication, the 401 (and hence the login box pops-up). This is (I guess) because angular is not able to populate the Authorization field in the header before the 401 hits the browser..
Solutions?
Have an async=false request using jquery?
Close the login-box when we are done getting the data we want. The login box might flicker...
Store more meta-data about the login (ie, username) in cookies, so we dont haveto do get this information from the server when the app is loading.
??
Is there a better solution? This one time, for this one request, I want async=false in my Angular resource....
The solution I went for (which works perfectly) is to set $http.defaults.headers.common['Authorization'] = 'Token ' + old_api_token;, before the async request. And then overwrite it when the async request is done (if it have changed).
I am starting to build/design a new single page web application and really wanted to primarily use client-side technology (HTML, CSS, JavaScript/CoffeScript) for the front-end while having a thin REST API back-end to serve data to the front-end. An issue that has come up is about the security of JavaScript. For example, there are going to be certain links and UI elements that will only be displayed depending on the roles and resources the user has attached to them. When the user logs in, it will make a REST call that will validate the credentials and then return back a json object that has all the permissions for that user which will be stored in a JavaScript object.
Lets take this piece of javascript:
// Generated by CoffeeScript 1.3.3
(function() {
var acl, permissions, root;
root = typeof exports !== "undefined" && exports !== null ? exports : this;
permissions = {
//data…
};
acl = {
hasPermission: function(resource, permission, instanceId) {
//code….
}
};
root.acl = acl;
}).call(this);
Now this code setup make sure even through the console, no one can modify the variable permissions. The issue here is that since this is a single page application, I might want to update the permissions without having to refresh the page (maybe they add a record that then needs to be added to thier permissions). The only way I can think of doing this is by adding something like
setPermission: function(resource, permission, instanceId){
//code…
}
to the acl object however if I do that, that mean someone in the browser console could also use that to add permissions to themself that they should not have. Is there any way to add code that can not be accessed from the browser console however can be accessed from code in the JavaScript files?
Now even if I could prevent the issue described above, I still have a bigger one. No matter what I am going to need to have the hasPermission functionality however when it is declared this way, I can in the browser console overwrite that method by just doing:
acl.hasPermission(resource, permission, instanceId){return true;}
and now I would be able to see everything. Is there anyway to define this method is such a way that a user can not override it (like marking it as final or something)?
Something to note is that every REST API call is also going to check the permissions too so even if they were to see something they should not, they would still not be able to do anything and the REST API would regret the request because of permissions issue. One suggestion has been made to generate the template on the server side however I really don't like that idea as it is creating a very strong coupling between the front-end and back-end technology stacks. If for example for whatever reason we need to move form PHP to Python or Ruby, if the templates are built on the client-side in JavaScript, I only have to re-build the REST API and all the front-end code can stay the same but that is not the case if I am generating templates on the server side.
Whatever you do: you have to check all the permissions on the server-side as well (in your REST backend, as you noted). No matter what hoops you jump through, someone will be able to make a REST call that they are not supposed to make.
This effectively makes your client-side security system an optimization: you try to display only allowed operations to the user and you try to avoid round-trips to the server to fetch what is allowed.
As such you don't really need to care if a user can "hack" it: if they break your application, they can keep both parts. Nothing wrong can happen, because the server won't let them execute an action that they are not authorized to.
However, I'd still write the client-side code in a way that it expect an "access denied" as a valid answer (and not necessary an exception). There are many reasons why that response might come: If the permissions of the logged-in user are changed while he has a browser open, then the security descriptions of the client no longer match the server and that situation should be handled gracefully (display "Sorry, this operation is not permitted" and reload the security descriptions, for example).
Don't ever trust Javascript code or the front-end in general. People can even modify the code before it reaches your browser (sniffers etc) and most variables are accessible and modifiable anyways... Trust me: you are never going to be safe on the front-end :)
Always check credentials on the server-side, never only on the front-end!
In modern browsers, you can use Object.freeze or Object.defineProperty to make sure the hasPermission method cannot be redefined.
I don't know yet how to overcome the problem with setPermission. Maybe it's best to just rely on the server-side security there, which as you said you have anyway.