
API with NestJS #3. Authenticating users with bcrypt, Passport, JWT, and cookies - mwanago
https://wanago.io/2020/05/25/api-nestjs-authenticating-users-bcrypt-passport-jwt-cookies/
======
adamkl
Nest.js is a great framework, with excellent documentation, but it can be
quite heavy weight (from a coding and concepts perspective) and alienating to
JavaScript devs without a background in C#/Java.

Its basically Spring/.Net MVC implemented in TypeScript. That makes it a great
choice for .Net/Java developers who are transitioning to coding for Node.js,
but for anyone without that background, it comes with a steep learning curve
(Dependency Injection, Inversion Of Control, Aspect Oriented Programming...
all the usual suspects of "enterprise" application development).

I'd say its positioned to become very popular (and you can see its trending
strongly upwards on npmtrends.com) because so many enterprises are
transitioning towards Node.js. Its like a cozy blanket for ex .Net/Java
developers.

I always find it amusing that that Nest.js is a back-end framework, that was
inspired by a front-end framework, which was inspired by a back-end framework.
(Nest.js -> Angular -> Spring MVC). :-)

~~~
slow_donkey
Strongly agree - as someone much more comfortable within the node ecosystem,
there's several libraries I'd rather use in place of Nest's choices. However
it makes a great starting point for people not aware of the other options and
who need an opinionated bootstrap.

If anyone's wondering my current template is routing-controllers, class-
validator, tssyringe, and sequelize-typescript.

Separate issue, but if anyone can suggest a different query builder / orm in
typescript that'd be truly appreciated. Imo typeorm is too much of an
abstraction and sequelize works but requires custom types ever since v5

~~~
bradyo
Until yesterday, I would've voted Prisma. There was actually a Show HN post
recently that debuted Zapatos:
[https://news.ycombinator.com/item?id=23273543](https://news.ycombinator.com/item?id=23273543).
The top comment also mentions mammoth:
[https://github.com/Ff00ff/mammoth](https://github.com/Ff00ff/mammoth).
Probably going to switch over to one of them as they're closer to raw to raw
SQl and well typed.

------
jakelazaroff
Stateless JWT for auth is one of the worst trends to catch on in the past few
years. Don’t do it – _always_ check your tokens against a database. Otherwise,
if someone compromises an account or gets their hands on a token, there’s
basically nothing you can do to stop them.

~~~
dvdhnt
Side note, the idea of JWT without verifying the token against a database,
made me doubt what I was doing.

I wasted too many cycles trying to understand how it was secure while debating
how much latency my database check was introducing on every single request
compared to those simply using the JWT as-is.

It has made something I considered "settled" to be a time-sink.

~~~
karatestomp
They don't make a ton of sense until your public-facing services get kinda
mesh-like. If it's all in one DB, including authorization and authentication
data, and you never have one service requesting resources from other services
on behalf of a user, they're probably overkill and regular sessions would be
fine.

(Nb. I've not personally seen them used in a case for which they make sense,
yet, but only in smaller projects because they're trendy)

------
_bxg1
Something that's come to light for me recently and which I'm trying to
understand the reasoning for, is bringing OOP patterns like singletons,
dependency injection, visitors, etc. over to a multi-paradigm language like
JavaScript. My understanding is that these were all basically clever hacks for
working FP and procedural concepts into a strictly OOP language (plain module-
level state, closures, and plain functions/pattern-matching, respectively).
But you can get the same advantages without jumping through any of those hoops
in JS and the like. Are they getting brought over purely as a comfort-blanket
to Java/C# devs or is there something I'm missing?

~~~
k__
Never understood this either.

But when I see how TypeScript looks like JS+C# it feels like OOP people just
can't help themselves

~~~
_bxg1
It really doesn't have to though. TypeScript can look like C# or it can look
like Haskell, or it can be one in some places and the other in other places.
This is my favorite property of [JT]S. You can simply use the best tool for
the task at hand.

------
cbg0
You may want to use Argon2id for password hashing instead of bcrypt, as it is
more secure. See
[https://security.stackexchange.com/questions/193351/in-2018-...](https://security.stackexchange.com/questions/193351/in-2018-what-
is-the-recommended-hash-to-store-passwords-bcrypt-scrypt-argon2)

~~~
ynniv
Unless you are have a formal proof of your entire application plus operating
system and enforce very long passwords, the choice between bcrypt and Argon2
isn't improving your security. Even if that describes your situation and
custom bcrypt silicon becomes available, you can buy some and increase the
work factor. Also if this describes your situation, trusting JWT is a huge
risk. For any web application, your time is better spent closing run of that
mill web vulnerabilities.

~~~
ryanlol
Why not use md5 then? You can always add more rounds.

~~~
tialaramex
I'd argue (though PHK himself disagrees) that yes, PHK MD5 crypt() is still an
acceptable choice in 2020 for exactly that reason. You can add a bunch of
rounds to defeat a reasonable attack, and it's unlikely this is your system's
weakest defence. Should you build new green field systems intentionally with
PHK MD5? No, no reason to. But you are kidding yourself if you believe that's
the weak point in an existing system or in a compatibility mechanism.

Toy systems that just do MD5(MD5(password)) are screwed because they don't
have any _salt_ , but PHK MD5 uses salt so all the time-space tradeoff attacks
are made irrelevant, bad guys will need to brute force each account they want
to attack individually.

If which crypto hash to use is a major security consideration you are already
Doing It Wrong™ because the only point of these systems is to store human
memorable passwords, and human memorable passwords are _hot garbage_ anyway.
Either outsource the human authentication problem to somebody else or, if you
are quite sure that's strategically unsound (e.g. you want to be Amazon or
Apple with fingers in every pie) then _require_ passwords not match
PwnedPasswords and either mandate or at least strongly encourage a second
factor, with at least TOTP and WebAuthn options offered.

------
benatkin
I haven't started using NestJS yet but am very impressed with the
documentation. Here is it introducing its Websocket and GraphQL support:
[https://docs.nestjs.com/websockets/gateways](https://docs.nestjs.com/websockets/gateways)
[https://docs.nestjs.com/graphql/quick-
start](https://docs.nestjs.com/graphql/quick-start)

~~~
virmundi
My team picked up NestJS as we've moved from Spring Boot/Java to Node Lambdas.
The ability to use CDK + NestJS to deploy a single Lambda to handle a few
endpoints is amazing. NestJS allows us to write code more in the Clean
Architecture style without it becoming really heavy like we see with Spring.
I've enjoyed it so much that I might use it for my person projects too
(leaning towards Dart for one language across the stack).

~~~
sdfin
Do you mean you lean towards using Dart for everything except for the backend?

~~~
virmundi
I want to use Dart for all of it. Recently Dart has a compiled version.
Another project integrates this with AWS Lambda. Might be nice.

------
enahs-sf
Having cognitive dissonance between all of these very similarly named js
frameworks. Next, Nuxt and Nest... is there some kind of weird inside joke
that I’m not in on?

~~~
aenario
Nuxt is Next for Vue.js, so it does make sense. Next and Nest are unfortunate,
always need to read it twice to be sure.

~~~
enahs-sf
Thanks for the clarification.

------
Kaze404
I love NestJS. With backend specifically I always recommend the more barebones
frameworks like Koa and Express to beginners so they can learn how all the
moving pieces interact with each other. But once you already know that, it's
so nice to use a framework that only needs you to tell it what to do (as
opposed to how, like in Express). I use it for all my pet projects in node now
:)

~~~
woutr_be
One of the things I took away from NestJS was the focus on dependency
injection, even doing that with Express made it so much better to develop
against.

It’s one thing I really hate about almost every tutorial or example that’s out
there, they just pull in dependencies out of nowhere.

------
ridicter
Nest.js + Angular on the frontend is a dream. Nest.js was modeled after
Angular and they both use a similar basket of concepts/tools (dependency
injection, decorators, first-class TS support). You can build a robust full
stack app without context switching. They are both opinionated, ensuring a
consistent and predictable structure.

If you go the Nest + Angular route, I recommend checking out NX monorepos,
which adds another level of seamlessness. NX was created by former
Google/Angular team members. One of my favorite features includes the ability
to easily share libraries/models across the front end and backend. E.g., if
you're designing an API, you can import the same model file to both the front
end and back end, ensuring no divergence between both sides as the API is
redesigned.

~~~
_bxg1
> One of my features includes the ability to easily share libraries/models
> across the front end and backend. E.g., if you're designing an API, you can
> import the same model file to both the front end and back end, ensuring no
> divergence between both sides as the API is redesigned.

To be fair this applies to _any_ case where you have the same language on the
front and back, which was one of the main motivations for Node in the first
place

~~~
ridicter
As far as sharing JS library code yes, but the baked in typescript support +
nx CLI add a lot in terms of usability.

1\. nx g @nrwl/workspace:lib data, 2\. Modify the typed models/interfaces. 3\.
Import to backend + front end.

------
varrock
I'm a front end developer, so NestJS was a blessing for helping me write my
API. It gave me a set of rules to follow and amazing utilities to make my life
easier, such as exception filters [0]. One thing I admittedly struggle with is
knowing when to create a new Nest Module versus a new service in an already
existing module, and I do not think Nest provides such guidance on application
architecture. However, I believe this is a result of my minimal back end
experience, and shouldn't be held against the NestJS project. Overall, I am
really enjoying it.

[0] [https://docs.nestjs.com/exception-
filters](https://docs.nestjs.com/exception-filters)

~~~
adatavizguy
> I admittedly struggle with is knowing when to create a new Nest Module
> versus a new service in an already existing module

I use the same logic as where to put a font end component. If I'm creating a
component for the first time, it sits in the same folder as the parent
component. If I need to use it with another component, I refactor it into a
common folder. If I create a string transformation function, it exists in the
same file that is using it. If I need to use it somewhere else, it gets
refactored into utils/strings.js which is a starting place for creating a
library.

It solves the problem of 'where does this go?' and 'where did I put it?' 95%
of code that I need to find will be physically next to the code that uses it
in a file system. If not it will be neatly organized into a common use
directory.

For the few times I need to refactor functionality, at that point, I will
invest time to make a clear and adaptable API input and output contract.

------
maallooc
Woah, I was trying to look at the source of bcrypt.compare and ended up at
[http://bcrypt.compare/](http://bcrypt.compare/).

Apparently .compare TLD hit General Availability in 6 May 2020.

~~~
hobs
Yet another example of tld poison that makes universal search bars even less
useful since anything with a period in it is now automatically a tld.

~~~
capableweb
Or, yet another example of how the universal search bars poisons the URL
handling in order for someone to drive up usage of their search traffic. Two
views of the same coin.

~~~
cptskippy
I've had the option to use the address bar as search set in Mozilla products
for as long as it's been an option (so like 20 years?) and it's only in the
last 2 or 3 years that it's become unreliable.

------
ksashikumar
I just started a project in NestJS. Prior to this I was working on express for
NodeJS backend where I had to do a lot of manual stuff and achieving
dependency injection across the application was a pain. I'm impressed with
NestJS so far. If I could go back in time and re-work the project, I'd choose
NestJS. I've also worked with Rails and Spring boot. With NestJS I get the
same ease and flexibility like in Rails and Spring boot.

Finally a great web application framework for NodeJS.

------
zacksinclair
I've built a large application with Nest as the backend and gotta say, nothing
but love for the framework. IMO it is the leader in typescript backend space.

Nest + Typeorm + Postgres + Apollo + NextJS for front end = best of many
worlds

------
_bxg1
I read six or seven comments down before realizing that this isn't Next.js.
Each time I noticed the "s" in someone's comment I assumed it was a typo. Not
a great naming decision to be one letter off from something else that's
closely related and in the same language.

------
eropple
I've spent the last eighteen months using NestJS. I can simultaneously call it
a good step forward in the Node space and something I wouldn't use for a new
project. They've done a lot of work to build a system that, so long as you
stay within very narrow lines and don't ask too many questions, feels very
cohesive and consistent. The unfortunate part is that it shakes apart at speed
if you don't do both of those things.

People make a lot of hay about the NestJS dependency injection system, and my
intuition is that a lot of it is that it's a novel concept to a lot of the
folks running into it. If you come from a Spring or related background,
however, I think it's pretty clear that NestJS has a pretty critical
misunderstanding of dependency injection. Modules are hardwired
together--`BarModule` requires `FooModule`rather than just declaring what they
_need_ and what they _export_ and allowing the dependency resolver to figure
it out regardless of what module they come from. As-is, you cannot replace a
dependency coming from `FooModule` with one, say, from `Foo2Module` without
changing _every consumer_. It's a high-boilerplate devolved service locator
rather than dependency injection.

"Pretty critical misunderstanding" has become my default description of big
parts of NestJS as I've gotten deeper into its use over the last year and a
half. This description really does fit a lot of aspects of the system. It
often feels as though the implementors read half a description of this or
that, decided "that's a great idea!", and then implemented that half-a-
description...poorly. The "microservices" concept (really just RPC, and not
particularly play-nice-with-others RPC) is a good example, as is the really
clunky access to WebSockets. CQRS is another prime example, as they've somehow
implemented _single-node CQRS_ , made it impossible to distribute, and
declared victory and went home.

It is better to _not provide official support_ for something if that official
support is going to be so full-stop awful, because that official support will
choke out attempts to innovate in the space because you've already taken the
mindshare for the problem at hand. Which dovetails into the problem that will
probably end up putting NestJS in the dustbin as soon as somebody else comes
up with a competitor: the NestJS team seems to have what feels like at best an
oblivious and at worst a rivalrous relationship with their community and with
Node as a whole. Over the last year they've rolled out what read to me as
lock-in, don't-play-nice-with-the-ecosystem-as-a-whole "features", like their
poorly intentioned CLI "monorepo tooling rather than just using lerna for
multi-modulestuff like the rest of the world. Also like the future-forecasted
"Nest CLI plugins" for things like linting otherwise bonkers misbehaviors[0].
As somebody who's written a bunch of open-source modules for NestJS, I
consistently get the feeling that Kamil would really prefer it if developers
just shut up and took his stuff and made apps (maybe paying him along the
way?), rather than building their _own_ open-source stuff alongside it. I
still have a very bad taste in my mouth from the way that they just stomped on
the `nest-schedule` project by added a less-featureful but otherwise identical
"cron-like" gizmo to NestJS core without so much as a nod to the community
member who wrote the better one before they did. The idea seems to be that
NestJS isn't a community, it's a single-source vendor, and in 2020 that's
weird to me.

I've used a lot of NestJS but I can't really countenance using it for new
projects, and I can't recommend it to others.

[0] -
[https://github.com/nestjs/nest/issues/3279](https://github.com/nestjs/nest/issues/3279)

~~~
adamkl
I don't have as much experience working with Nest.js as you do, but I can see
some validity in some of the things you mention.

Nest.js tries to have "answers" for everything (i.e. CQRS, MQTT, Kafka, etc.,
etc., etc), but I do wonder how well implemented these answers are (vs.
checking of a list of "completed" features.. Their documentation certainly
looks impressive when it comes to breadth).

I think if you stick to the core concepts of MVC with some simple DI (and if
you are building something that pushes the limits of that DI system, maybe its
too big), Nest.js can take a team of developers new to Node.js and enable them
to quickly build well structured applications (certainly with higher quality
than the average express applications I've seen in the wild).

Do I think its the perfect swiss-army knife of Node.js server side
development? No, but for a team of regular developers, I think it fills an
important void in the Node.js landscape (the same void that was filled by
Spring MVC in Java).

As with everything tech related, it all depends on the use case.

~~~
eropple
I don't disagree with anything you've said. But, that said, I feel like
there's a brick wall there for NestJS users and I feel like the incentives of
the NestJS core team are hard to ascertain. Uncertainty creates risk; if
you're comfortable with that level of risk, that's great. I'm growing to not
be comfortable with it.

If there was a roadmap and a set of principles for governance I'd feel much
better about it, but I also have trouble seeing that ever actually happen.

 _> I do wonder how well implemented these answers are_

Not well, tbh. "Microservices", as mentioned, are useless. CQRS is
fundamentally misunderstood. Their OpenAPI 3 libraries (and I will cop to some
bias here, my frustration with their OAS implementation got to the point where
I wrote a better one[0]) are implemented in a developer-unfriendly way that's
totally separated from validation so there's a ton of diplication of work.
(And let's not even talk about validation! `class-validator` is a mess.
"Pipes" are pretty silly as a concept. Fastify uses `ajv` under the hood;
there's not a great reason why everybody else doesn't, too.)

As you say: checkmarks. A lot of checkmarks. But then you pick up the corner
of the carpet and the subfloor's chewed through.

[0] - [https://github.com/eropple/nestjs-
openapi3](https://github.com/eropple/nestjs-openapi3)

------
nicoburns
I've been keepig an eye on nest.js for a while now. I haven't had a chnace to
use it yet, but from the docs it looks like the closest thing to a rails-style
framework in Node land. Albeit less mature/comprhensive than
rails/django/laravel.

~~~
AlphaWeaver
Another project in this vein in the JS ecosystem that's starting up right now
is Redwood [0]. I'm optimistic, considering it's backed by Tom Preston Warner.

[0]: [https://redwoodjs.com](https://redwoodjs.com)

~~~
egeozcan
Those magic functions for named routes though... I'm not sure such magic would
do well with typescript

------
baby
Please use a “password hash” to store your hashes. The best practice algorithm
is Argon2.

