Express Gateway gives you the ability to spin up your own oauth provider from the command line. Oauth enables your users to delegate API endpoints to various apps via scopes. In this introductory article, you'll learn how to get up and running with Oauth in Express Gateway.
The first step is to create a new gateway using the Express Gateway generator. First, install the express-gateway
npm module, and then create a new gateway using eg gateway create
.
$ npm i -g express-gateway
$ eg gateway create
? What's the name of your Express Gateway? oauth
? Where would you like to install your Express Gateway? oauth
? What type of Express Gateway do you want to create? Getting Started with Express Gateway
create package.json
create server.js
create config/gateway.config.yml
create config/models/applications.js
create config/models/credentials.js
create config/models/users.js
create config/system.config.yml
To start oauth, run the following commands:
cd oauth && npm start
$
Second, edit the config/gateway.config.yml
file and enable oauth for the default
pipeline as shown below. Once you turn on oauth,
you should see an 'Unauthorized' error when you visit http://localhost:3000/ip
. You need to restart the server
for config changes to take effect, so if you ran npm start
be sure to kill the process and then re-run npm start
.
http:
port: 8080
admin:
port: 9876
hostname: localhost
apiEndpoints:
api:
host: localhost
paths: '/ip'
serviceEndpoints:
httpbin:
url: 'https://httpbin.org'
policies:
- basic-auth
- cors
- expression
- key-auth
- log
- oauth2
- proxy
- rate-limit
pipelines:
- name: default
apiEndpoints:
- api
policies:
# The below enables oauth for the localhost:8080/ip endpoint
- oauth2:
- proxy:
- action:
serviceEndpoint: httpbin
changeOrigin: true
Next, you'll need to create a new Express Gateway user. Users and applications have a one-to-many relationship, so you must create a user before you create an application. Make sure you do not restart the express gateway server after creating a user unless you have already set up a data store, because otherwise express gateway will use an in-memory data store and all your users will be deleted if the process is killed.
$ eg users create
? Enter username [required]: val
? Enter firstname [required]: Valeri
? Enter lastname [required]: Karpov
? Enter email: val@karpov.io
? Enter redirectUri:
✔ Created c25fe037-30bb-42f7-9f3a-0264dcd60d14
{
"firstname": "val",
"lastname": "karpov",
"email": "val@karpov.io",
"isActive": true,
"username": "val",
"id": "c25fe037-30bb-42f7-9f3a-0264dcd60d14",
"createdAt": "Wed Aug 16 2017 22:08:07 GMT-0700 (PDT)",
"updatedAt": "Wed Aug 16 2017 22:08:07 GMT-0700 (PDT)"
}
Next, you need to create 2 credentials for this user: an
oauth credential and a basic-auth (password) credential. Express Gateway has a one-to-many relationship between users and credentials, so a user can have multiple credentials of different types (OAuth, key-auth, basic, etc.). The below creates an oauth credential and a basic-auth
credential with password "bacon". Note that password
doesn't show up in the output of
eg credentials create -t basic-auth
, that's for security.
$ eg credentials create -c val -t oauth2
✔ Created val
{
"isActive": true,
"createdAt": "Wed Aug 16 2017 22:08:13 GMT-0700 (PDT)",
"updatedAt": "Wed Aug 16 2017 22:08:13 GMT-0700 (PDT)",
"id": "val",
"secret": "45e94fce-1524-4fbf-89b9-57a157079db7"
}
$ eg credentials create -c val -t basic-auth -p "password=bacon"
✔ Created val
{
"isActive": true,
"createdAt": "Wed Aug 16 2017 22:08:21 GMT-0700 (PDT)",
"updatedAt": "Wed Aug 16 2017 22:08:21 GMT-0700 (PDT)",
"id": "val"
}
Finally, you need to create an application, or "app". The app represents a consumer of your API. Similar to how an app might use Facebook login and request access to the user's photos, an Express Gateway app will log in against Express Gateway and receive permission to access a certain set of API endpoints. To create an app, you need to specify an associated user, a name, and a redirect URI, which is the URL the user will be directed to after successfully logging in.
$ eg apps create -u val
? Enter name [required]: testapp
? Enter redirectUri: http://google.com
✔ Created 84828eee-2832-4ecd-8155-008fbea0f485
{
"name": "testapp",
"redirectUri": "http://localhost:8080/ip",
"isActive": true,
"id": "84828eee-2832-4ecd-8155-008fbea0f485",
"userId": "val",
"createdAt": "Wed Aug 16 2017 22:08:38 GMT-0700 (PDT)",
"updatedAt": "Wed Aug 16 2017 22:08:38 GMT-0700 (PDT)"
}
Now that you've set up the necessary objects, let's walk through the actual oauth flow using Chrome and cURL. You'll notice that if you visit http://localhost:8080/ip
in Chrome you'll get an 'Unauthorized' error message as shown below.
Your gateway.config.yml
file protects the /ip
endpoint behind oauth middleware, so you need to get an access token by walking through the Express Gateway oauth flow. To start, you need to visit the /oauth2/authorize
endpoint and specify the following parameters in the URL query string:
response_type
: String containing either 'bearer' or 'token'. For this example you'll use 'token'.client_id
: String containing the id of your app from the output ofeg apps create -u val
. In this case, '84828eee-2832-4ecd-8155-008fbea0f485', but it will be different for you.redirect_uri
: String that must match theredirectUri
you specified when running theeg apps create -u val
command.
Here's how the full URL looks:
http://localhost:8080/oauth2/authorize?response_type=token&client_id=803b1da9-879d-44b5-8d77-5199c4e11fba&redirect_uri=http://localhost:8080/ip
When you visit this URL, you should get redirected to a login screen. You can configure the UI, but for this article you'll just use Express Gateway's minimal built-in login screen.
Enter in the username and password you entered when you ran eg users create
. If you're following this article exactly, the username will be "val" and the password will be "bacon". You will then get redirected to a page that asks you to authorize your app 'testapp' to access your account. In more advanced applications, this is also where Express Gateway will ask for other permissions (scopes).
Hit the 'Allow' button to continue the flow and you'll get an 'Unauthorized' error. Don't panic, you didn't do anything wrong, this is actually the right behavior. Oauth is all about granting API access to client apps, and does so by putting the access_token
in the URL. This is the access token you use in the Authorization
header in your HTTP requests to authenticate to the oauth policy. Your app will have to do that on its own, but, in the interest of keeping this example lean, you'll just use curl.
Copy the access_token
from the URL bar. The access_token
is URI-encoded, so first decode it using Node.js's shell.
$ node
> decodeURIComponent('599f481560a74545a0f9d54a2e3f7dde%7Cb1f7252fe6f24a0d98d98cc87693579c')
'599f481560a74545a0f9d54a2e3f7dde|b1f7252fe6f24a0d98d98cc87693579c'
>
Next, use curl
to make an HTTP request with the token in the Authorization
header as shown below:
$ curl -H "Authorization: Bearer 599f481560a74545a0f9d54a2e3f7dde|b1f7252fe6f24a0d98d98cc87693579c" http://localhost:8080/ip
{
"origin": "76.220.52.187"
}
$
Congratulations, you've successfully generated an access token through Express Gateway's oauth flow and used it to make an authenticated request!
This article is just a "Hello, World" level example for oauth with Express Gateway. In this example you used Express Gateway as both the auth server (the server requesting auth) and the resource server (the server granting access to the API). However, Express Gateway can also serve as an auth server for an external API, so you can add OAuth permissions on top of any API. I'd recommend you try actually building a client-side app that uses Express Gateway oauth for login, and read up on scopes so you can control which portions of your API your app has access to.
hey @vkarpov15 think this looks great! maybe just want to mention that for this walkthrough exercise, we're using the Express Gateway built in memory DB and that's why you shouldn't restart after you created credentials