
Run your own OAuth2 server - machete143
https://www.ory.am/run-oauth2-server-open-source-api-security.html?
======
StavrosK
Isn't the "problem" with this that you can't get arbitrary websites to talk to
your OAuth2 server? For example, even though, say, Gitlab, supports OAuth2
login with Github, I can't get it to authenticate with stavros.io.

This is the problem Portier
([https://portier.github.io/](https://portier.github.io/)) and OIDC aim to
solve, ie to be able to auth on any website with an auth instance you run.

I love this idea because it's much easier to secure _one_ thing whose sole
purpose is authentication than to secure _every_ thing you want to
authenticate on.

~~~
machete143
I'm not sure if I understood you correctly. Delegation of authentication
usually implies trust between the two parties. GitLab (the hosted version)
does probably not trust stravros.io enough to allow people to log in through
there.

Portier looks indeed very nice, maybe I'll set up a tutorial how to get those
two working together to get full Authentication (portier) + Authorization
(Hydra) with using only open source technology.

~~~
icebraining
Why does Gitlab have to trust anyone? It's the user that has to trust
stravros.io not to tell Gitlab that other people are authorized.

It's no different than a regular email/password (with password recovery): if I
register with user@stravros.io, then that email server becomes empowered to
give access to the Gitlab account to anyone it wants. But that's not Gitlab's
problem.

See also OpenID.

~~~
StavrosK
Exactly, and OpenID connect adds an authentication layer over OAuth2 for this
exact purpose. If we manage to build that future, it will be very useful and
quite exciting, at least to me. There won't be compromised passwords any
longer, just the one password you can easily change.

~~~
lucaspiller
You are ten years too late. The original OpenID did exactly this, and quite a
few sites (especially tech focussed sites) let you sign in with it. Except
then along came Google and Facebook with their proprietary login systems, and
everyone jumped ship to those as they offered access to profiles rather than
just a domain and possibly email address.

~~~
dboreham
We first worked in this problem at Netscape just after the AOL acquisition in
1998. It turns out to be impossible because: show me the money. Something we
figured out within a few weeks back then.

~~~
cat199
Which is precisely why DNS and SMTP have failed miserably.

~~~
garfij
Please elaborate on how DNS has failed? It seems to me that everyone uses DNS
all the time and is an essential component of the Internet as we know it, but
you and I may have differing notions of failure.

~~~
mike-cardwell
I assume he was being sarcastic

------
andreareina
> _Please use more secure values in production. ;)_

That's not going to stop people from using those exact values. How many
breaches have we seen due to the lack of sane defaults? Tutorial code
(especially when written by the people putting out the software) is a default,
and it's likely to result in plenty of people running this exact code in
production.

~~~
machete143
That is a valid concern. However, once a password is published (especially in
docs or tutorials) it is insecure whether they are random values or not -
simply because they are public and clearly linked to the product you're
running.

That's why I chose to make it explicit, and thus more likely to be caught in
review if done.

~~~
tempay
I'd suggest using something like:

    
    
      export SYSTEM_SECRET=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
      echo "SYSTEM_SECRET is $SYSTEM_SECRET"

~~~
machete143
Good idea! How could that look like on windows (the guide should work on all
OS and I'm no windows pro)?

~~~
casselc
Rough equivalent in PowerShell would be:

    
    
      @(48..57 + 65..90 + 97..122) | Get-Random -Count 32 | ForEach-Object -Begin {$secret = ''} -Process {$secret += [char] $PSItem} -End {$env:SYSTEM_SECRET = $secret; Write-Host "SYSTEM_SECRET is $secret"}

~~~
koolba
My Powershell-fu isn't quite up there. What's the first part of that block? Is
that concatenating arrays of ranges of char codes?

~~~
casselc
Yes, it just creates an array of the decimal values for ASCII A-Za-z0-9. By
default Get-Random just returns a random unsigned int, but if you pass in an
array of objects it will select a random object from the array.

------
machete143
If you're not into reading the article itself and want to check out the
technology first, here's the link to github:
[https://github.com/ory/hydra](https://github.com/ory/hydra)

If you have any questions, feel free to ask ahead.

------
tinco
Is not running Postgres in Docker in production still a thing? What kind of
problems are people running into? I love having everything managed using the
same deployment techniques and I was on a team that ran Postgres in Docker in
production for a couple of years and never ran into trouble. Of course that
doesn't mean anything so I am curious.

~~~
_ix
I'd like to know, too! I'm working on a side project and aiming to run
containerized docker for production – can anyone weigh in?

~~~
XorNot
It's advice born from people who don't quite understand docker. Postgres in
containers just needs a data volume on a dedicated drive for speed, and you
need to remember dockers default stop behaviour hard kills after 10s which is
not long enough for a clean shutdown (use docker kill to send sigterm and
wait).

------
ourcat
Worth adding to this that Wordpress have been working on an official OAuth1.0a
server plugin for while alongside the development of the new REST API. It
works well. I've built an iOS app on the back of it. (1.0a was chosen due to
WP not wanting to enforce https.) [https://en-gb.wordpress.org/plugins/rest-
api-oauth1/](https://en-gb.wordpress.org/plugins/rest-api-oauth1/)

I've also seen discussion on an official OAuth2 server plugin, what with the
rapid increase of https sites, thanks to the likes of LetsEncrypt.

There's a well supported OAuth2.0 server plugin here: [https://en-
gb.wordpress.org/plugins/oauth2-provider/](https://en-
gb.wordpress.org/plugins/oauth2-provider/)

But you'd be wise to only run it via https.

~~~
machete143
Yes indeed, running OAuth2 without https is madness!

~~~
unilynx
It's not just madness, TLS is a MUST in several places in the oauth2 spec.

In fact, they managed to remove a lot of oauth1 madness (all the complex
signing stuff) by simply requiring TLS and let that layer deal with it.

------
manigandham
Also worth mentioning IdentityServer:
[https://identityserver.io/](https://identityserver.io/)

------
zrail
SAML doesn't get enough love. Big _big_ companies want to use your software
but really need to use their existing SAML-compatible identity provider. When
you don't support it they'll move on to someone who can.

Conversely, if your organization has a SAML-compatible IdP you get to work
with a vast sea of compatible software without really having to think about
the integration. Exchange metadata URLs, maybe some URL templates, and you're
done.

------
EtienneK
Worth mentioning Keycloak as well:
[http://www.keycloak.org/](http://www.keycloak.org/)

I've been playing around with it recently and it seems to be a very capable
OIDC/Oauth2 provider indeed.

~~~
willow9886
The issue with Keycloak is that it is never patched.

> Think of Keycloak as bleeding edge with quick releases, unpatched, and
> limited community support. [1]

Seems fine for research, but using it in production seems risky.

[1]
[http://www.keycloak.org/support.html](http://www.keycloak.org/support.html)

~~~
EtienneK
RedHat SSO is the production-ready version of Keycloak:
[https://access.redhat.com/products/red-hat-single-sign-
on](https://access.redhat.com/products/red-hat-single-sign-on)

------
krullie
I've been jumping between hydra and dex for the last couple of weeks. On the
one hand I like the tight focus hydra has, with the exception of the warden
api. On the other hand it is really involved to simply setup a working
environment that includes hydra ready to go. It would be nice to do all the
token, client and policy setup using a simple docker-compose up.

Dex for example has a dev mode doing that for you. The downside of Dex is you
cannot use your own backend without forking the project, writing your own
login page and creating a custom connector for your existing login system.

~~~
machete143
Thank you for the valuable feedback! The dev mode is indeed a very good idea -
I'll probably spin up another docker-compose example with all the default
things set up. Would that make it easier?

~~~
krullie
Yes definitely. Although you could build a new image based off of the original
one, add a bash script that sets it all up for you and overwrite the
entrypoint i never like that sollution. It should be something that the
software supports out of the box as it plays into one of the strengths of
docker, easily spinning up and taking down instances.

------
richardknop
Interesting work. Especially for me as I have spend a lot of time delving into
OAuth2 spec during my career and I have my own competing solution :)

See it here: [https://github.com/RichardKnop/go-
oauth2-server](https://github.com/RichardKnop/go-oauth2-server)

Available as docker container. You can simply deploy it via docker-compose up.

Yours seem to be better maintained though :)

~~~
machete143
Looks interesting, does this solve authentication as well? It looks like it
but from quickly scanning through the readme I didn't find anything.

Also what's your reasoning for relying on 4 (etcd, consul, postgres, nats)
external dependencies?

~~~
richardknop
Hi, you can use resource owner password credentials grant which is part of
OAuth2 spec:

[https://github.com/RichardKnop/go-oauth2-server#resource-
own...](https://github.com/RichardKnop/go-oauth2-server#resource-owner-
password-credentials)

It's basically a login with username and password.

If you want a fully fledged identity provider on top of OAuth2 (so create /
update user account, password reset), I have a sample project which extends on
the oauth2 repository and builds a full identity provider on top of it:
[https://github.com/RichardKnop/example-
api](https://github.com/RichardKnop/example-api)

About dependencies: only two are required - etcd/consul and postgres. There is
no other requirements.

Originally I developed this project while deploying to a CoreOS cluster so
etcd was a native choice for storing app configuration in a distributed key
store. Consul support was added later in form of a contribution as an
alternative to etcd.

I also want to remove dependency on etcd/consul completely and allow just
simple configuration via environment variables to make the projec more
portable.

~~~
machete143
What I meant to ask is if this has things like user registration, password
reset flow, two-factor authentication, account takeover prevention, etc.

I think removing 3rd party dependencies is always a good idea - it keeps
things lean and removes ops overhead.

~~~
richardknop
No it doesn't have things like user registration password reset flow etc. I
wanted to keep the project just as straight OAuth2 server based on spec,
nothing more.

I have another project which I sometimes use as a boilerplate when working on
ideas and I need a simple API for my prototyping. It contains all those things
as registration, password reset flow etc:

[https://github.com/RichardKnop/example-
api](https://github.com/RichardKnop/example-api)

~~~
machete143
So how do people grant tokens then? They do need to log in somewhere?

~~~
richardknop
The go-oauth2-server contains simple web forms (which you can style to match
your UI) to handle the full authorization and implicit flows of OAuth2 so you
would connect to the oauth2 server from your app, log in and be redirected
back to the app with authorization code and then the app can obtain access and
refresh tokens from the oauth2 server via API call.

This is a normal authorization flow people are used to from
Facebook/Github/LinkedIn, works the same way. See README for images of how the
forms look out of the box, without any customization.

If you want to have in app login system, then for such scenario usual way I
have implemented this before is to have a separate frontend layer and it works
something like this:

1) Frontend (mobile/web app) displays login form

2) Enter username and password

3) Use resource owner credentials grant to obtain access token via API call

4) Now you can make authenticated API calls with the access token (and use
refresh token in the background to renew your access token)

In case of web application frontend (let's say NodeJS app), the app would
store client ID and secret server side (so you would proxy all requests from
client app to Node proxy because we don't want to keep client ID and secret in
public JS).

------
ernsheong
Unfortunately Hydra does not (and will not) support the resource owner
password credentials (ROPC) grant
([https://github.com/ory/hydra/pull/297#issuecomment-294282671](https://github.com/ory/hydra/pull/297#issuecomment-294282671))

I'm no security expert, but to my understanding the ROPC grant makes sense for
highly privileged applications, i.e. 1st party client applications (e.g. main
app website, main native iOS client) as explained by
[http://oauthlib.readthedocs.io/en/latest/oauth2/grants/passw...](http://oauthlib.readthedocs.io/en/latest/oauth2/grants/password.html)

I've been looking around in this space for OAuth and auth out of the box
alternatives. I've tried Kong's OAuth2 plugin
([https://getkong.org/plugins/oauth2-authentication/](https://getkong.org/plugins/oauth2-authentication/))
but after trying to integrate it felt like I had to write more code than
necessary. Also had to configure a lot of APIs, and felt like it was clunky to
manage them that way.

I have also tried to play with [http://anvil.io](http://anvil.io), but the
authors are busy with another project
([https://solid.mit.edu](https://solid.mit.edu)) so Anvil is taking a back
seat. Even the Getting Started currently has known unfixed issues.

I am heavily investigating
[http://www.keycloak.org/](http://www.keycloak.org/), and so far I am really
impressed. However though, to deploy you will need to delve into Wildfly/Java
configurations. And of course, minimum 512MB to run any Java app on a node.

Dex is also advertised as a solution but it looks like the documentation could
do with more information and improvements.
[https://github.com/coreos/dex](https://github.com/coreos/dex) Doesn't seem
easy to just take and run.

Thanks to comments here, I might these looking at these next:

1\. [https://github.com/RichardKnop/go-
oauth2-server](https://github.com/RichardKnop/go-oauth2-server) 2\.
[https://portier.github.io/](https://portier.github.io/)

------
rawfan
If you're looking to add an OAuth2 server to your PHP app, check out Laravel
Passport
([https://laravel.com/docs/5.5/passport](https://laravel.com/docs/5.5/passport)).

------
gallerdude
I already have a hard time with OAuth Client!

~~~
clintonb
What problems are you facing? Practically every language I have worked in has
a third-party library for dealing with OAuth 2.0.

~~~
gallerdude
I was trying to make it work in Unity with reddit stuff...

------
kennydude
If you're using Django, Python Social Auth tends to go a good job at this
without any extra servers.

~~~
clintonb
PSA is a collection of authentication clients for authenticating with third-
party auth providers (e.g. Google, Facebook, Microsoft). If you want to run
your own auth provider server, you will need another library. We use Django
OAuth Toolkit ([https://github.com/evonove/django-oauth-
toolkit](https://github.com/evonove/django-oauth-toolkit)) at edX.

------
raarts
Worth mentioning: login.gov

------
homakov
If your sole purpose is authentication w/o authorization, one should use
securelogin.pw which does not depend on identity provider. And btw OAuth2 spec
is insecure by design, it's a known fact.

~~~
ForHackernews
> btw OAuth2 spec is insecure by design, it's a known fact.

OAuth2 is only "insecure" in that it relies on TLS for its security: the same
as HTTP, IMAP or SMTP. You should never run OAuth2 over a non-HTTPS (i.e.
HTTP) connection. The same is true for any other login system.

This is covered in RFC 6819:
[https://tools.ietf.org/html/rfc6819](https://tools.ietf.org/html/rfc6819)

~~~
homakov
Not just that, a couple of other bad decisions that caused made many websites
inherently insecure [https://sakurity.com/oauth](https://sakurity.com/oauth)

~~~
machete143
That is a really bad specification with no examples, no formalization, and
zero references.

However, all server-side attack scenarios listed there are not possible with
Hydra. Some of them also boil down to misusing OAuth2 for authentication,
which is why we have OpenID Connect.

~~~
homakov
No, ignore the spec (it's just a list of traits i'd like to suggest), design
issues are outlined after it.

