Preamble / TL;DR
I've got a dumb API using the PassportJS JWT strategy that I'd like to add sessions to for the purpose of having user isolation in certain areas, a requirement for some enhancements.
The entire system is comprised of a MySQL DB, NodeJS + ExpressJS (with PassportJS) backend and an Angular 2 frontend.
Further Information
I've had an issue with implementing sessions in my application, and experienced the same issues as seen in this Github Issue.
My frontend doesn't seem to handle the session id stored in the session cookie with the key 'connect.sid', even though a user can be correctly authenticated initially and get their JWT. The session cookie does however get used when bypassing the frontend and using POSTMAN to send the requests.
The primary symptoms of the issue I'm experiencing are:
The session cookie is not created when using the Angular2 frontend. Sending the requests using POSTMAN seem to have the cookies created.
The req.isAuthenticated() call is always false as a result (unless using POSTMAN)
I've now deduced it must be an issue with communication/handling of requests/responses between the front/backend.
I've spent the last couple days running through other issues like:
Ordering/checking use statements: here, here
Adding the respective headers to responses on the front and backend: here
And a couple others. I do however draw the following questions from this:
Question(s)
Is it even correct implementing sessions with a JWT strategy, knowing the two should be exclusive from one another?
If not, what would you recommend be done in this scenario?
Related
I'm really struggling to wrap my head around the concept of protecting ones API end point.
How do you do you protect it from abuse if it's exposed with React?
I understand if a user were to login then be issued them with a token etc. I get that. But let's say have a front end that does not require someone to be logged in?
They simply filling out a form with their details and it gets passed via you API then gets stored in the DB.
Whats stopping someone just abusing your API? They could just write a script and attack you end point with spammy data?
I just can't understand how this is protected?
you can set CORS headers, allowed hosts and also rate limiter for protecting your APIs in Django.
Allowed hosts: A list of strings representing the host/domain names that Django site can serve. This is a security measure to prevent HTTP Host header attacks, which are possible even under many seemingly-safe web server configurations.
CORS headers: Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading resources. It's used for working with browser clients.
Rate limiting: A rate limit is the maximum number of calls you want to allow in a particular time interval. For example each unauthenticated user can only do 100 requests per minute.
And also if you are deploying your app in a PaaS service then you can deploy your django app as an internal service and your react app as an external service. Then Django is not only usable inside the containers not outside them.
I have a web application, where the frontend is built with react.js and typescript and the backend is build with ASP.NET Core 3.1 and connected to a SQL Server. The SQL Server is used for saving data, which I can enter in the frontend.
Now I want to implement a custom authentication system, where I can protect different endpoints with an authorization. I know there are several ways to go for, but I don't want to use a service / library, where a user could login with his google account for example.
Jwt seems in my Opinion a good way to go here, but I really don't understand the whole system.
This article helped me already a lot: Implementing authentication and authorization with React hooks, .NET Core Web API, and SQL Server .After reading this, I don't understand the relationship between logging in and how my backend knows, that a user is logged in (for protecting my endpoints).
Of course I already read many articles about authentication and authorization for ASP.NET Core. I've read about different services like:
Auth0 (seems not a good idea, because you can login with google etc.)
IdentityUI (seems good, I've seen a few youtube tutorials but they are all using another project structure, where the frontend and backend isn't separated. So they are using the razor pages like Login.cshtml, but I don't want to render any pages in the backend, only in the frontend)
For authorization for my controller in the backend, I planned to use the following:
[Authorize] // to protect endpoint
[HttpGet]
public async Task<IEnumerable<>> GetData()
{
// some code
}
But as I already said: I don't know / understand how my backend knows if a user is logged in (and how to check it).
Could somebody provide me an appropriate tutorial or an article, where is explained, how to manage authorization and authentication for frontend and backend? Or maybe somebody knows, how to use the IdentityUI with a frontend build with react + typescript and a backend, which shouldn't render any pages.
Thanks for your attention :)
Well... for detailed flow how they work, here is RFC 6749, this is a pretty comprehensive collection of knowledge related to the topic and the easiest approach would be wiki page in general.
But to simplify the process, just get to know these things:
What is JWT
Jwt just a string that was generated by some algorithm from a public/private key pair(don't even care how it works, just give it a key pair, some lib on every language would do the rest). This JWT often contain all the information that needed to specify who the user is(big word right ? but actually, userId is enough for simple case).
It contain 3 different parts Header, Payload and Signature, and the string assured it cannot be interrupted(or just modify it as we wish, and the validation process would failed).
Further detail here.
What happen on server side?
The most basically flow was send user, password to server for validate who we are and our account exists. Then, server side would take some necessary info out of it to generate the JWT token. The server which generate JWT token was normally refer to Identity Provider.
Then that token was send back to client, and client save it somewhere for later use.
Client side use token to request other resource
Normally, Identity Provider would provide a .wellknow endpoint that contain all necessary info for other resources to gather for validation process.
Now, client side send a http request to these resources with the JWT token. They use info gathered from .wellknow endpoint to validate was the JWT valid. If it is, we are who we claim we are, authentication process success.
The end.
Over-simplyfied flow imagination in your specific case
React Client => Request login => Identity Provider => Jwt Token send back => React client save it somewhere.
React Client => Request some resource over http with the JWT token => Resource server validate it (through info from .wellknow endpoint) => Authentication success or fail => normal process => send response back to client.
I have 4 angular applications one is a landing app which asks user to login and has to redirect the user according to its type
to one of the other 3 applications. I am unable to figure how to should i achieve that.
Have the three apps running on different subdomains. Upon login backend send a redirect response, figuring out what type of user it is?
But this leads to cors Error. Also i am not sure whether the cookie which i am setting will be accessible in all the subdomains or not.
Is there a way out?
You can do a redirect, but it seems like an unnecessary step (and kind of convoluted for this type of application).
Instead of returning a redirect based on login, it seems more straightforward to just return the address you want to redirect to in the response. Trigger a lookup to determine which app you should be directing to (however you're doing that) and then return the address of the app in the response data. From within Angular, you can extract the address from within response.data in $http. (see angular docs). The nice thing here is you also keep routing control and knowledge of state within Angular itself.
As for the apps themselves--instead of a subdomain, you can simply put the apps into different folders on your domain. This deals with CORS and the cookie issue.
Otherwise, you'd need to set a CORS header. You would do this on whatever backend you're sending the requests to--there's usually some sort of library to make it easy, for example, Flask CORS for Flask. If you need to share cookies in this case, this StackOverflow answer discusses one way of doing it (using an intermediary domain).
Generate a security key for the user session with some TTL in an authentication table when you authenticate the user with your App1
Redirect the user to any other app in any domain with this security key where they can query the authentication table and verify the user.
Let these other applications work on their own (in the front end) and communicate with the back-end with the security key when necessary.
Lot of PHP frameworks has built-in support for this mechanism. My favorite is Silex.
I need some advice regarding using session tokens to authenticate users. I am building an AngularJS app which uses an API to tie in with the backend. I am only building the front end, not the backend. The documentation states that all calls to the API have a session token attached in the body of the request (POST).
I would like to know about the security of storing this token in localStorage. That is where I am storing it now and retrieving and attaching it to each API request. After login, the server sends the session token in the body and I save it from there.
There is no documentation about an x-access-token header that should be sent with the request made to the server. It is not being checked server side. What are the implications of this? I feel that it is susceptible to attacks without this added layer of security.
My main concern is the security of this setup. I want to know what the best setup is to make sure this app is as secure as possible and recommend changes to the way the backend is setup to facilitate this.
Thanks!
As you tell, you are only working on the UI part and not the backend. It is up to the backend team to ensure headers are properly evaluated and security is enforced (btw request headers do not belong to request body). Just put the token into the x-access-token header as they tell.
Storing the token inside the localStorage gives you a little more control over the cookie: You will not accidentally send it to unnecessary URLs. However, older browsers do not support it - you may need to use a shim for that.
In a case of SPA, you may consider not storing the token at all: It could be fetched each time your application is accessed and then stored within a service in angularjs, but it depends how your fetch/login operation is implemented (is it always interactive, how long does it take, etc).
I would suggest use $cookies rather than localstorage. As localstorage does not support some legacy browser.
I am using cookies to store token in my project
I have an Angular application (SPA) that communicates with a REST API server and I'm interested in finding out the best method to store an access token that is returned from an API server so that the Angular client can use it to authenticate future requests to the API. For security reasons, I would like to store it as a browser session variable so that the token is not persisted after the browser is closed.
I'm implementing a slightly customized version of OAuth 2.0 using the Resource Owner Password grant. The Angular application provides a form for the user to enter their username and password. These credentials are then sent to the API in exchange for an access token which must then be sent as a header (Authorization: Bearer %Token%) for all outbound requests to the API so that it can authorize requests to other routes.
I'm fairly new to the realm of Angular, but the workflow I would like to implement as far as handling these tokens is summarized as follows.
1) The client makes a request to the API providing it with user credentials.
2) If this request is successful, the token is stored somewhere (where is the question)
3) Intercept HTTP requests. If token is set, pass it along as a header to API
4) Token is destroyed when the browser/tab is closed.
I know Angular offers $window.sessionStorage, which appears to be what I am looking for, but I am concerned by the potential for it not to work on all browsers according to various resources I've read. This is an enterprise grade application and must be compatible across a broad range of browsers (IE, Chrome, Firefox). Can I safely use this with the confidence that it will be stable?
The alternatives, from what I understand, are either $window.localStorage or cookies ($cookies, $cookieStore). This would not be an ideal solution for me since I don't want this data to persist, but if this is more reliable I'll have to sacrifice efficiency for compatibility. I was also thinking it might be possible to simply set it as a value on the $rootScope and reference it this way, but I'm not sure if this is feasible.
I hope that all made sense. Any help / suggestions would be greatly appreciated.
Thanks!
If you are looking for something that will definitely not persist then I would simply keep the token in memory and not rely on the browser for storage. However storing inside rootScope would not be best practice.
I would recommend that you wrap your server access code in an Angular Service if you have not done so already. You can then encapsulate your token within that Service at runtime (e.g. as a property) without worrying about having to access it when calling from other parts of your application.
Angular Services are singleton so your "server service" will be a global instance that can be accessed using normal dependency injection.
$window.sessionStorage is the way to go unless you're targeting very old browsers.
According to www.w3schools.com sessionStorage is supported from IE 8.0, Chrome 4.0, Firefox 3.5, and Safari 4.0.