1. Don't build your own OAuth 2 server.
And if you're just doing auth for your own apps - not providing auth services for third parties to integrate with - I wouldn't suggest using OAuth at all. It's much more complicated and you're much more likely to make mistakes.
It isn't a bad idea to (carefully) read and learn from the principles of the OAuth 2 spec in order to make your own auth services, but I'd generally suggest avoiding making an OAuth server by hand unless you are very experienced in doing this. There are a lot of silly mistakes you can make due to the over-complication.
2. Don't use passwords.
It's 2018. Passwords are really not a good way to secure your system. You're going to end up building an email-based password reset system anyway right? So just cut to the chase and use magic-link based login only. It's pretty easy to do securely.
3. Keep it simple.
If you're implementing something you don't fully understand, or think you probably understand, but haven't considered every possibility, you're likely to introduce vulnerabilities. A simple auth protocol which you fully understand will perform better than a complex one you don't understand.
> It isn't a bad idea to read and learn from the OAuth 2 spec in order to make your own auth services
has actually lead to quite horrible auth systems. I've seen bad stuff in large enterprises due to this ("we're smarter, we'll solve it for our use case" -> "Oops, we didn't think about session replay").
I recommend OAuth2 for complex systems with many involved parties and clients. There it can really reduce complexity. For normal apps with maybe 1-2 consumers, cookie-based security is secure and good enough!
Assuming you have fully read and understood the OAuth spec, I find that it can be a helpful resource to identify the more complex considerations that might be easily missed in a home-grown auth implementation.
That being said, in my company's case, I haven't entirely followed my own advice, and we did implement our own OAuth 2 server. But we do know the spec pretty comprehensively.
Edit: if anyone's interested in our particular flavour of the protocol, we have it documented at https://github.com/cuvva/docs/blob/master/apis/auth.md#send_...
>It's 2018. Passwords are really not a good way to secure your system. You're going to end up building an email-based password reset system anyway right? So just cut to the chase and use magic-link based login only. It's pretty easy to do securely.
I'm no security expert but isn't email notoriously insecure? I also find checking my email every time I have to log into a service or app is poor user experience. Are there better even more secure ways of implementing a no password system?
Magic link tokens are one-time-use anyway, so assuming you follow the authorization code spec, if any attempt is made to use the code a second time, you should revoke any existing auth tokens which resulted from that code. So the risk here is pretty low. You can also further mitigate this by implementing PKCE, which prevents any other client/app/whatever from using the code.
Also bear in mind most apps are able to store access/refresh tokens securely, so don't tend to have any kind of auth timeout. For most apps which allow magic-link login, your "session" will never expire, so it isn't particularly problematic to have to log in via an email link.
For a website, there's no major reason you shouldn't have a reasonably long-lasting cookie to prevent any need for regular login.
If you're concerned about long-lasting sessions, it might be appropriate to use a second authentication factor for sensitive actions - e.g. purchases, transferring money, etc.
Other than pairing with MFA/2FA, there isn't really anything meaningfully more secure than (properly implemented) email magic link auth. Assuming you want decent usability and your audience isn't overly technical, magic links are definitely the way to go as a primary authentication mechanism.
What happens if the cookie is stolen (real question) ? Wasn't that the problem in keeping connection / session information in cookies back in the days ?
If you have a client-side-only site, probably best to use local storage instead.
Otherwise, marking them as HTTP-only and secure-only should be sufficient.