AngularJS JWT local authentication doubts - angularjs

I'm currently developing a MEAN based application, I was thinking about the Angular JWT local authentication.
The backend API verifies the token server-side, so is no problem, but in the client-side authentication is handled locally.
What happens if someone tries to modify the authentication scripts locally?Will he bypass the authentication?In the case how can I avoid the problem?

Your client side app only contains views, empty html, but no data. It's usually ok to let anybody see that, view structure need not be a secret in most cases.
You are saying the server does authenticate the user though, which is fine, only authorized data should be returned and filled in the view templates.
To put it in other words, there is no such thing as client side authentication in this sense. That's more like a ux feature to not show funcionality that the user cannot access anyway.

Related

AWS Cognito Identity Service Provider appears to store access token in local storage. Is this safe?

We are developing an application that uses a React front end website hosted on AWS using Amplify. This communicates with a .NET Core 3.1 Web API running on EC2 / Elastic Beanstalk. Cognito is used for user authentication with the Web API configured to use JWT tokens.
It works OK, but we have noticed that the Cognito provider stores the JWT access token in the browser local storage. This is what we see using F12 in Chrome and inspecting local storage.
From what we have read, storing access tokens in local storage is not advised as it makes the application susceptible to XSS attacks. Strange then, that the Cognito identity provider chooses to store sensitive information here.
If this approach is not considered safe, can the provider be configured to store this information elsewhere, such as cookies?
Alternatively, as we control both front and back ends, is there an alternative method that can be used to secure the API that does not involve tokens? Obviously the API needs to know which user is logged on to the web application in order to perform authorization checks. [Note authorization in the application is record level and defined in database tables, so it goes beyond simple user profile attributes.]
Many thanks in advance for your advice.
Doug
Security is a spectrum not a feature so it really depends on your appetite for risk vs effort. Amplify is not a particularly nice codebase, it has 500+ issues and if you look at the code you might be fairly shocked at the quality of it.
If you are using Hosted-UI then you can write code to manage the tokens yourself rather than using amplify, although you will need to learn a bit about OAuth grants and OIDC.
Be aware that the Hosted UI lacks a huge amount of features, so if you are going to use it make sure you are happy with it. Off the top of my head
no silent refresh capability in the hosted UI, so no safe way to store the refresh token.
no support for custom auth flow in the hosted UI
no passwordless support in the hosted UI
no ability to pre-populate a field in the hosted UI (e.g. username)
no ability to customise the plethora of obscure error messages in the custom UI
fixed now, but for years the email addresses were case sensitive!
An alternative is also to just use the AWS SDK to get tokens directly using cognito-idp but this also has a bunch of issues:
no code/PKCE/nonce capability so insecure in a mobile authsession
no ability to set oauth scopes, so can't use them
consequently not possible to use for OIDC
the SRP implementation is bananas and so far off spec
if you make device registration mandatory, it will deliver a working access tokens before the device is registered! (allows invisible devices for malicious logins)
We were using auth0 which was leagues ahead but we had to move to Cognito because of SMS OTP cost (min $25k per year at auth0).
I have been using AWS for over a decade now, Cognito is by far the worst service I have used, and I have used a lot! If you can avoid it, do so.
To answer the original question, yeah it's insecure. The best you can probably do is keep them in memory. If you wanted to you could probably put the hosted UI behind a cloudfront and use an lambda#edge to transform the token into a cookie instead. This has now opened you up to CSRF attacks though.
answering the original question: no, it is not safe at all.
Storing refreshtoken in any local storage accessable to any local app/script is not secure. So, the best way would be to store the refreshoten (and also the access token) in an httponly cookie or even better to store a one-time session token in httponly secure cookie could be used to get new access and refresh cookies - similarly as it is made by cognito hosted ui with XSRF-TOKEN.
See below how I would solve (and plan to solve) this issue:
Some background:
Due to GDPR regulations I think I can not use the cognito hosted ui - I have to make sure users read and accept the general terms and conditions (giving clear and auditable consent) and can review and accept cookie policies as well before they type in any user data for sign up. Nevertheless the built in hosted ui design is quite outdated and unflexible. I have an SPA website where I want to manage users, secure endpoints, etc.
So I have the following idea which is still not super secure but I think it is more secure one if you want to use js and ampify sdk and which also might answer your question:
I'll use amplify javascript sdk to let users sign up, change psw and log in (get tokenid, access token and refresh token), will make my own "hosted ui". I'll store the access token in memory only (not in local cookies and not in localstorage for sure). Access token will be used in header (bearer) to access apiGW endpoints. Access tokens will have very short expire dates. (I'd also use httponly secure cookies sent back by the apigw, as well as in the body.., then compare at BE side..)
And here comes the trick: I'd cut the refresh token into two. (Don't forget it is just a string.) I'd store the first part of the string in a local cookie (javascript can read it, if browser is closed and opened again it will be still there) and will send the other half of the refresh token to an apiGW endpoint (accessable without authentication) which will store it in a dynamoDB table (with TTL) and will send back an httponly secure cookie to the browser with a randomly generated "storagetoken" in it (which will be a key in dynamodb). There will be another unauthenticated apigw endpoint which will be called by the client whenever the client needs the full refresh token. Calling this endpoint the browser will send in the httponly secure cookie as well (same domain), so the backend will get it. As it is issued by the BE and available only in the given browser it can not be stolen so the backend will send back the stored half refreshtoken. The other half part of refreshtoken is stored in a simple cookie in the browser.
If the browser is closed and opened again client checks if there is any valid accesstoken and if not it checks if there is a half refeshtoken stored as cookie. Then ask the other part of refreshtoken assuming there is a httponlycookie also stored and it will get back the other part of the refreshtoken from the BE. In case of success the client tries to use the full refreshtoken to renew/get access token from cognito, in case of failure it will pop up the login screen.
Whenever refreshtoken is not in use it is deleted from the memory.
I know this is still not supersecure but might be a better solution than storing refresh token in localstorage.
Alternatively, as we control both front and back ends, is there an alternative method that can be used to secure the API that does not involve tokens?
I don't know anything of Amplify but in AWS Cognito what you describe is the Implicit grant OAuth flow. In AWS Cognito it is possible to use Authorization code grant where you instead of the token get a code which you in the backend can exchange for a user pool token.
https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-configuring-app-integration.html

ReactJs security

I have just started learning authorization and authentication in react, and I'm writing this after finishing my first simple login system using JWT, as most of you know you store a token in the browser and then you compare it with the saved tokens in your backend now when that validation is done truly I set Authenticated Boolean to true and gain access to the website, after finishing that simple system I checked react dev tools and I found out that I can just change the boolean to true and bypass all of the authentication work!
And I have searched online for resources and tutorials to fix that massive problem but didn't find what was I looking for all I found is how to setup Authentication or protect a router similar to the way I did, but not deeply secured.
So can anyone recommend a course or tutorial paid or free to learn more about security and authentication?
Since React apps are single page apps (if you are doing client-side rendering), the entire application (all html/css/js files) is sent to the client in the initial request. Generally authentication works in the way you have stated where the authentication status of the user is stored in the application state. This, of course, means that someone familiar with web applications would be able to set the variable isAuthenticated to true. If you have sensitive information kept statically (written literally in html/css/js) then this would be an issue.
The reason this scenario is not generally seen as an issue is because React apps usually do not hold any data. And data is usually the sensitive stuff in an app. Data can be tied to the user and should not be exposed to those who are not properly authenticated or do not have the required permissions. Data is held by the server, which can control what it sends out (checking for verified JWTs) via the API to the app. So your server should check for a valid JWT on any request that returns sensitive information—generally all requests except those for the app itself and authentication requests.
In short: Yes, someone can get access to the "authenticated" side of your app, but any requests to the API for data by the app at this point would (or should) be blocked as unauthorized (i.e. status 401). So they can see what the app looks like to an authenticated user, but would not be able to see any sensitive information.
(Note: if you do store sensitive information statically (as mentioned above), consider storing it on the server and having the app request that info via the API and requiring a valid authentication token).
If you would like to block the possibility of an unauthenticated user gaining access to the authenticated side of your app, you could make the login page its own app or HTML doc and only send the full/authenticated version of the app to authenticated users.

Authenticate with Google Drive API in AngularJS

I created this web app completely in go-lang, which uses Google Drive API to authenticate users. Once user authenticated, it saves the token in a <user-email>_token.json file so the app can operate for 24 hours without the users involvement. It works fine. But now I want to separate the front-end from (Go-Lang)back-end and convert it to AngularJS.
So I have this problem with authentication. Because I should keep the authentication in server-side. But then how would Angular know that the user is authenticated or not? Because I cannot use sessions.
Should I need to use JWT to this? If it is, then how should I do it?
Your token does not have to be on the server side.
Why? Because if you have many clients connected to your server, it would mean that all of these clients are sharing the same token and therefore have access to the Google Drive linked to this token. It does not make sense.
The token has to be on the client side. You should save the token as a cookie, maybe by using JWT, I let you read the documentation of JWT to know why it would be interesting to use it in your case or not.
Then on your Angular, you have to say something like "hey, this client has a cookie called "my-google-drive-token", let's check if that is a good one... Mmmmh, okay seems to be good, I display the Google Drive content".
Think about using good practices about security (using an encrypted token in your cookie, making the connection between the front and the back safe, keep your API key safe...).
Your backend is only a gateway between your front-end and the Google Drive API.
Also, check the usefulness of your server. I think that in your case, a simple frontend connected to the Google API is enough.

AngularJS best practice application authentication

I'm start building a web application where the user needs to authenticate in order to get access to different modules.
I have been working with ASP.NET MVC in the past and it was quite easy using FormsAuthentication and Server Sessions so I don't have to do roundtrips to the database in order to get the user roles or any other user related data everytime I access a web method.
What I have been reading, AngularJS won't work that way so there won't be any Server Session, etc.. So...
In case I need to verify user identity every time I access a web method do I need to consume database or there is any good practice that I can learn of?
I know there are ways to store state data in client side but how that can affect the performance of a web application?
I have seen that when a user login to an application the best way is to send a Token to the client and then force AngularJS to send that Token everytime a web method is accessed... but what about sending to the client the user sessionId (from database) and then on every web method consumption sending that and then create a filter where you check that the sessionId exists in the database so the user identify is validated?
Appreciate any advice or recommendations.
Thanks.
My take on authentication is that you do not need to bring AngularJS into picture till the user is authenticated. You use simple login page and authenticate user and then redirect him to your app page that has Angularjs. Look at my old answer for more details How to handle authentication in Angular JS application
Let me try to address your concerns.
In case I need to verify user identity every time I access a web
method do I need to consume database or there is any good practice
that I can learn of?
Once you have been authenticated that part is taken care by server and browser cookies, you don't need to do anything. How standard MVC site works.
I know there are ways to store state data in client side but how that
can affect the performance of a web application?
Since AngularJS is a SPA, there is no page refresh. Data stored at $rootScope or using service are there till one refreshes the page. Performance would be better as there are less round trips involved.
I have seen that when a user login to an application the best way is
to send a Token to the client and then force AngularJS to send that
Token everytime a web method is accessed... but what about sending to
the client the user sessionId (from database) and then on every web
method consumption sending that and then create a filter where you
check that the sessionId exists in the database so the user identify
is validated?
This is standard form authentication, and transparent to developer, whatever was required to be done in traditional MVC app for authentication would work here. You don't have to worry about sessionids, tokens etc. To get users identity on the client, you can write a angularjs service with methods such as getUser to get the current logged in user. But i warn you that the authorization related decision should still be done on server.

Example of an SPA with a login screen that uses AngularJS and connects to ASP.NET Web API 2?

I would like to create a new AngularJS, Web API Single page application. Does anyone have any examples that show how I can set up a user login screen that connects to a WEB API controller for a simple login (no need for google/facebook login etc) that uses ASP.NET Identity and without the need for user registration.
Also how can I handle showing a new view once the login has been completed. What I would like is to have a solution that does not show routing in the browser URL. So for example I would like to be able to switch from the login view and a couple of other different views without the url changing from www.abc.com.
In other words I would like to avoid showing www.abc.com/login, www.abc.com/screen1, www.abc.com/screen2
Any advice would be much appreciated.
So, instead of trying to find an example, I created one instead (link at the bottom). To explain how the functionality works, I want to go over a few things:
The new ASP.NET Identity system provides an OAuth 2.0 Bearer token implementation which can be used with clients that consume a Web API resource over HTTP. Since the authentication is not stored in a session cookie, the server is not responsible for maintaining the authentication state. The side-effect is that the consumer has to manage authenticating the server and managing the returned token. This is the system that Microsoft uses in the SPA template that it provides with VS 2013.
AngularJS makes no assumptions about authentication, so it's up to you how to authenticate.
AngularJS provides the $http service for querying remote HTTP-based services as well as $resource which is built on top of $http. Using Authorization headers with the Bearer token implementation above, you can combine both to provide authenticated access to server resources over HTTP. AngularJS allows you to set a 'default' Authorization header which it will use in every subsequent HTTP transaction.
With that in mind, the way I accomplished this is by creating a User service that handles all of the authentication details, including setting the HTTP Authorization header, between the Web API server and the SPA. Based on the authentication status of the user, you can hide certain UI elements in order to prevent navigation. However, if you also define the state as requiring authentication as a property of the resolve object for the state, a watcher set on the $stateChangeError event will capture the error and redirect the user to the login form. Upon proper authentication, it will then redirect the user to the state they were trying to navigate to.
In order to prevent authentication from being lost between browser sessions (since the client is responsible for maintaining the authentication token, and that token is maintained in memory), I also added the ability for the user to persist the authentication to a cookie. All of this is transparent to the user. For them, it is practically identical to traditional form-and-session based authentication.
I'm not sure why you want to prevent the user from seeing the routes, but I have coded it as such. I am in debt to Sedushi's Plunker example of how to use AngularUI Router to navigate in a stateful manner without using URLs. Still, I'm not sure I can personally recommend this for any application I would write on my own.
The full solution (both the WebAPI and the WebUI) is available with step-by-step instructions here.
Let me know about any specific part that is unclear, and I will try to make it more clear in the answer.
Refer the following blog for the demo of single page application (SPA) for ASP.NET Web API 2 and AngularJS, developed by the team at Marlabs.
http://weblogs.asp.net/shijuvarghese/archive/2014/01/25/demo-spa-app-for-asp-net-web-api-2-and-angularjs.aspx
The app is built with following technologies:
ASP.NET Web API 2
EF 6 Code First
AutoMapper
Autofac
Semantic UI
AngularJS 1.1.5
The application is published on github at https://github.com/MarlabsInc/webapi-angularjs-spa.
#DavidAntaramian gave a great example. But if you want a simple one, you can look to this HOL from Microsoft.
Their latest example on github uses .NET Core, but you can download release from October 2015.

Resources