RUN YOUR OWN
OAuth2 Server

api security using SECURE AND
scalable open source technology

In this guide, you will set up a hardened, fully functional OAuth 2.0 (OAuth2) server. It will take you about ~15 minutes. This guide is for you, if you are looking to do something like in the gif on the right, or more specifically:

  • You want to use OAuth2 for API security.

  • You want to open up your API to third party developers like Dropbox, or GitHub.

  • You want to become and identity provider like Google, Facebook, or Twitter.

  • You need to federate (delegate) authentication or authorization.

We will use ORY Hydra (open source), a security-first OAuth2 and OpenID Connect server written in Golang.

Let's start by downloading some docker images. By the way, this tutorial relies heavily on docker. If you haven't already, please install docker now.

my-anchor

Install and run PostgreSQL

First, a database is required, and we will choose PostgreSQL 9.6 (MySQL is also supported).

This docker command starts postgres container ory-hydra-example--postgres and sets up a database called hydra with user hydra and password secret.

$ docker run \

--name ory-postgres \
-e POSTGRES_USER=hydra \
-e POSTGRES_PASSWORD=secret \
-e POSTGRES_DB=hydra \
-d postgres:9.6

By the way, don't deploy databases using docker in production. It will make your life miserable. Use a managed solution like Amazon RDS or Google Cloud SQL. Even small instances will be able to serve a lot of traffic, check out some of the benchmarks.

my-anchor
white

Configure the environment

$ export SYSTEM_SECRET=y82XL-wAPCCZu+B4

System Secret

The system secret is used to encrypt data at rest, and to sign tokens and authorize codes. Once a database is initialized with a system secret, you always need to use that secret to access the database.

$ export DATABASE_URL=postgres://hydra:[email protected]:5432/hydra?sslmode=disable

Database

The database url must point to the postgres container we created above. The database will be used to persist and query data. ORY Hydra protects against data leaks as only token signatures are stored in the database. For a valid token, both payload and signature are required.

$ docker pull oryd/hydra:latest
$ docker run \
--link ory-postgres:postgres \
-it --entrypoint \
hydra oryd/hydra:latest \
migrate sql $DATABASE_URL

Initialize the database

The database needs to be initialized next, which can be achieved with hydra migrate sql. Here we pull the latest docker image for hydra and run a container that executes the migrate command.

my-anchor

Run the OAuth2 server

Besides setting the system secret, the database url, the public url of the server (issuer) and the root client (use that to manage Hydra), a consent url are passed using environment variables.

The consent url points to a web service which will be explained and set up in the next sections. It connects Hydra to your identity management.

Please use more secure values in production. ;)

$ docker run -d \

--name ory-hydra \
--link ory-postgres:postgres \
-p 9000:4444 \
-e SYSTEM_SECRET=$SYSTEM_SECRET \
-e DATABASE_URL=$DATABASE_URL \
-e ISSUER=https://localhost:9000/ \
-e CONSENT_URL=http://localhost:9020/consent \
-e FORCE_ROOT_CLIENT_CREDENTIALS=admin:demo\
oryd/hydra:latest

Is it alive?

This is easy to answer, just check the docker logs! Or, open the health check, which should show you ok. If asked, accept the self signed certificate in your browser.

$ docker logs ory-hydra

[...]
time="2017-06-29T21:26:34Z" level=info msg="Setting up http server on :4444"
my-anchor
white

Generate and validate tokens

$ docker run -p 9010:4445 \
--link ory-hydra:hydra \
-it --entrypoint "/bin/sh" \
oryd/hydra:latest

SSH into bash container with Hydra

In this section, you will connect to the Hydra instance and generate and validate access tokens for the root client. To save you the trouble of installing Hydra locally, SSH into a container running bash with the ORY Hydra command line interface (CLI) installed.


$ hydra connect


Cluster URL []: https://hydra:4444
Client ID []: admin
Client Secret [empty]: demo-password

Connect with Hydra

The command line interface (CLI) needs to know where Hydra is and what client id and secret should be used (FORCE_ROOT_CLIENT_CREDENTIALS).

$ hydra token client --skip-tls-verify

tY9tGakiYAUn8VIGn_yCDlTahckSfGbDQIlXahjXtX0.BQlCxRDL3ngag6hdsSl9N2qrz7R399cQMfld8aI2Mlg

Issue an access token

Using hydra token client it is possible to obtain an access token for the client we used during hydra connect, in our case that's admin.

Because only a self-signed TLS (for HTTPS) certificate is available, all interactions must skip TLS certificate verification which can be achieved with the flag --skip-tls-verify.

$ hydra token validate \
--skip-tls-verify \
$(hydra token client --skip-tls-verify)

{
"active": true,
"sub": "admin",
[...]

Validate an access token

Using hydra token validate it is possible to validate an access token, and receive it's payload. ORY Hydra uses opaque tokens to greatly reduce attack vectors. The payload of the token can be modified using the consent response (explained in later sections).

You can validate access tokens using the Introspection API, standardized as IETF OAuth 2.0 Token Introspection.

my-anchor

The consent flow

ORY Hydra is not an Identity Management solution, instead, it uses your existing Identity Management which reduces adoption complexity. OAuth2 providers such as Keycloak, OpenAM, or IdentityServer are usually full-stack enterprise identity and access management solutions. They come with complex deployment dependencies, technologies not particularly suited for cloud native environments, and subtle, but annoying limitations at scale. ORY Hydra solves OAuth2 and OpenID Connect only, but it solves it well and extremely scalable.

To authenticate users, ORY Hydra defines the consent flow. Expand this spoiler to learn more about how the consent flow works, by clickingthis paragraph or the chevron on the right. Example consent apps are available for Go and Node as well as Consent SDKs for both languages.

Create a consent client

The consent app requires a registered OAuth 2.0 Client with permissions to access cryptographic keys. The keys are required for validating and signing the consent challenge and the consent response.

$ hydra clients create --skip-tls-verify \

--id consent-app \
--secret consent-secret \
--name "Consent App Client" \
--grant-types client_credentials \
--response-types token \
--allowed-scopes hydra.keys.get

Create access control policies for consent client

ORY Hydra uses access control policies internally. This functionality is exposed as the Warden API. Since the consent app requires access to cryptographic keys, an access control policy for consent-app has to be created.

Read more about access control policies.

$ hydra policies create --skip-tls-verify \

--actions get \
--allow \
--id consent-app-policy \
--resources rn:hydra:keys:hydra.consent.<.*> \
--subjects consent-app

Run the consent app container

Since there is an exemplary consent app for NodeJS available, let's use that one in docker and connect it to ORY Hydra.

$ docker run -d \

--name ory-consent \
--link ory-hydra:hydra \
-p 9020:3000 \
-e HYDRA_CLIENT_ID=consent-app \
-e HYDRA_CLIENT_SECRET=consent-secret \
-e HYDRA_URL=https://hydra:4444 \
-e NODE_TLS_REJECT_UNAUTHORIZED=0 \
oryd/hydra-consent-app-express:latest
my-anchor
white

OAuth2 + OpenID Connect Authorize Flow

Create OAuth2 Consumer App

Awesome, the infrastructure is now set up! To perform the OAuth 2.0 and OpenID Connect flow, an OAuth 2.0 Client (consumer app) is required.

The client must be able to request the authorize_code grant, scopes openid and offline, and response types token, code, and id_token.

$ hydra clients create --skip-tls-verify \

--id some-consumer \
--secret consumer-secret \
-g authorization_code,refresh_token,client_credentials \
-r token,code,id_token \
--allowed-scopes openid,offline \
--callbacks http://localhost:9010/callback

Client ID: some-consumer
Client Secret: consumer-secret

Perform OAuth 2.0 Authorize Code Flow

To initialize an OAuth 2.0 authorize code flow, use the hydra token user command. It will generate the authorization url which the user must open in the browser. Requesting the authorization is the first step of the OAuth 2.0 authorize code flow

$ hydra token user --skip-tls-verify \

--auth-url https://localhost:9000/oauth2/auth \
--token-url https://hydra:4444/oauth2/token \
--id some-consumer \
--secret consumer-secret \
--scopes openid,offline,hydra.clients \
--redirect http://localhost:9010/callback

Setting up callback listener on http://localhost:4445/callback
Press ctrl + c on Linux / Windows or cmd + c on OSX to end the process.
If your browser does not open automatically, navigate to:

https://localhost:9000/oauth2/auth?client_id=some-consumer&redirect_uri=http%3A%2F%2Flocalhost%3A9020%2Fcallback&response_type=code&scope=openid+offline+hydra.clients&state=hfcyxoqoctwbnvrxrsuwgzfu&nonce=lbeouolavuvcdhjefcnzlqur

Access Token, Refresh Token & ID Token!

Once you logged in and granted some scopes, ORY Hydra will issue an access token and optionally a refresh (if scope offline was granted) and ID token (if scope openid was granted).

That's it, you have a running OAuth2 server with an exemplary identity provider! ORY Hydra is an Apache 2.0 licensed Go server solving OAuth 2.0, OpenID Connect and API security in general. It secures several production systems around the world and has a vibrant and welcoming online community.

my-anchor

Check out ORY Hydra at Github and check out our
API Security products.

my-anchor
white