Code Monkey home page Code Monkey logo

kong-oauth2-hello-world's Introduction

OAuth 2.0 Hello World for Kong

This is a simple node.js + express.js + jade application that demonstrates a simple implementation of the OAuth 2.0 authorization page required to make the OAuth 2.0 plugin work on Kong.

Files

This project is made of two main files:

  • app.js, which handles the server and contains two routes:
    • GET /authorize, that shows the authorization page to the end user
    • POST /authorize, that handles the form submit and triggers the authorization process on Kong
  • authorization.jade, which is the authorization page that the user will see

Installing dependencies

Execute

npm install

Setting up the environment

To run this project, execute the following operations.

  • Make sure you have Kong >= 0.10.3 running. We assume Kong is running at 127.0.0.1 with the default ports.

  • Let's add a simple test service:

curl -X POST \
  --url "http://127.0.0.1:8001/services" \
  --data "name=mock-service" \
  --data "url=http://mockbin.org/request"
  • Let's add a route for that service:
curl -X POST \
  --url "http://127.0.0.1:8001/services/mock-service/routes" \
  --data 'hosts[]=mockbin.org' \
  --data 'paths[]=/mock'
  • Now try the new API:
curl -X GET \
  --url "http://127.0.0.1:8000/mock" \
  --header "Host: mockbin.org"

The result should be a json response, containing an echo of the request that was sent.

  • Let's add the OAuth 2.0 plugin, with three available scopes:
curl -X POST \
  --url http://127.0.0.1:8001/services/mock-service/plugins/ \
  --data "name=oauth2" \
  --data "config.scopes=email, phone, address" \
  --data "config.mandatory_scope=true" \
  --data "config.enable_authorization_code=true"

This will output a response including an auto-generated provision_key that we need to use later:

{
    "service_id": "2c0c8c84-cd7c-40b7-c0b8-41202e5ee50b",
    "value": {
        "scopes": [
            "email",
            "phone",
            "address"
        ],
        "mandatory_scope": true,
        "provision_key": "2ef290c575cc46eec61947aa9f1e67d3",
        "hide_credentials": false,
        "enable_authorization_code": true,
        "token_expiration": 7200
    },
    "created_at": 1435783325000,
    "enabled": true,
    "name": "oauth2",
    "id": "656954bd-2130-428f-c25c-8ec47227dafa"
}

The provision_key will be sent by the web application when communicating with Kong, to securely authenticate itself with Kong.

  • Now try the new API again, to see it is now protected:
curl -X GET \
  --url "http://127.0.0.1:8000/mock" \
  --header "Host: mockbin.org"

This results in an error now (generated by Kong), since the proper credentials for access are missing.

  • Let's create a Kong consumer (called thefosk):
curl -X POST \
  --url "http://127.0.0.1:8001/consumers/" \
  --data "username=thefosk"
  • And the first OAuth 2.0 client application called Hello World App:
curl -X POST \
  --url "http://127.0.0.1:8001/consumers/thefosk/oauth2/" \
  --data "name=Hello World App" \
  --data "redirect_uris[]=http://konghq.com/"

That outputs the following response, including the client_id and client_secret that we will use later:

{
    "consumer_id": "a0977612-bd8c-4c6f-ccea-24743112847f",
    "client_id": "318f98be1453427bc2937fceab9811bd",
    "id": "7ce2f90c-3ec5-4d93-cd62-3d42eb6f9b64",
    "name": "Hello World App",
    "created_at": 1435783376000,
    "redirect_uri": "http://konghq.com/",
    "client_secret": "efbc9e1f2bcc4968c988ef5b839dd5a4"
}

Running the web application

Now that Kong has all the data configured, we can start our application using the provision_key that has been returned when we added the plugin.

Export the environment variables used by the Node.js application:

export PROVISION_KEY="2ef290c575cc46eec61947aa9f1e67d3"
export KONG_ADMIN="http://127.0.0.1:8001"
export KONG_API="https://127.0.0.1:8443"
export API_PATH="/mock"
export SERVICE_HOST="mockbin.org"
export SCOPES="{ \
  \"email\": \"Grant permissions to read your email address\", \
  \"address\": \"Grant permissions to read your address information\", \
  \"phone\": \"Grant permissions to read your mobile phone number\" \
}"

Note: By default, the application listens on port 3000. You can modify this if you like:

export LISTEN_PORT=3301

Then, start the authorization server:

node app.js

Testing the Authorization Flow

To start the authorization flow we need to simulate the request that the client application will execute when redirecting the user to your API. This request will include the response_type parameter, the client_id and the scope requested.

Note: In our example we are skipping the log-in of the user, which is something you will do in production before showing the authorization page.

With your browser, go to http://127.0.0.1:3000/authorize?response_type=code&scope=email%20address&client_id=318f98be1453427bc2937fceab9811bd to show the authorization page. You will see a page like:

Authorization Prompt

After clicking the "Authorize" button, you should be redirected to the redirect_uri we set up before with a code parameter in the querystring, like:

http://konghq.com/?code=ad286cf6694d40aac06eff2797b7208d

For testing purposes we set the redirect_uri to http://konghq.com, but in production this will be an URL that the client application will be able to read to parse the code and exchange it with an access token.

Conclusions

Done! Now the client application has a code that it can use later on to request an access_token. From a provider perspective our job only consists in showing the authorization page and redirecting the user.

To retrieve an access_token you can now execute the following request:

curl -X POST \
  --url "https://127.0.0.1:8443/mock/oauth2/token" \
  --header "Host: mockbin.org" \
  --data "grant_type=authorization_code" \
  --data "client_id=318f98be1453427bc2937fceab9811bd" \
  --data "client_secret=efbc9e1f2bcc4968c988ef5b839dd5a4" \
  --data "redirect_uri=http://konghq.com/" \
  --data "code=ad286cf6694d40aac06eff2797b7208d" \
  --insecure

The resulting json will contain the access_token as well as a refresh_token:

{
    "refresh_token": "N8YXZFNtx0onuuR7v465nVmnFN7vBKWk",
    "token_type": "bearer",
    "access_token": "njVmea9rlSbSUtZ2wDlHf62R7QKDgDhG",
    "expires_in": 7200
}
  • Now try the API again, but include the access_token we just received:
curl -X GET \
  --url "http://127.0.0.1:8000/mock" \
  --header "Host: mockbin.org" \
  --header "Authorization: bearer njVmea9rlSbSUtZ2wDlHf62R7QKDgDhG"

The result should be a json response once again, containing an echo of the request that was sent. Since the proper token was included, Kong will now validate the token and allow access again.

Note in the response that Kong injected a number of extra headers before sending the request to the upstream service:

    ...
    "x-consumer-id": "77e3f7ca-a969-48bb-a6d0-4a104ea7ad1e",
    "x-consumer-username": "thefosk",
    "x-authenticated-scope": "email address",
    ...

kong-oauth2-hello-world's People

Contributors

alvindaiyan avatar donmartin76 avatar jerneyio avatar jheijmans avatar knrt10 avatar lpmi-13 avatar ryanaoh avatar subnetmarco avatar tieske avatar xbazhen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kong-oauth2-hello-world's Issues

wrong scopes

Wrong scopes after run the curl script:
curl -X POST
--url http://127.0.0.1:8001/services/mock-service/plugins/
--data "name=oauth2"
--data "config.scopes=email, phone, address"
--data "config.mandatory_scope=true"
--data "config.enable_authorization_code=true"

Following is the output:
{"created_at":1545989589,"config":{"refresh_token_ttl":1209600,"enable_client_credentials":false,"mandatory_scope":true,"provision_key":"TcHMQJvT7Iyk2tPlFYuqbJkUlHEYVW1a","accept_http_if_already_terminated":false,"hide_credentials":false,"enable_implicit_grant":false,"global_credentials":false,"enable_authorization_code":true,"enable_password_grant":false,"scopes":["email, phone, address"],"anonymous":null,"token_expiration":7200,"auth_header_name":"authorization"},"id":"a66aba0d-070c-4256-ae09-f2988b61ae9f","service":{"id":"9e6c0e17-70c8-4f9b-9604-7bbce191cb22"},"enabled":true,"run_on":"first","consumer":null,"route":null,"name":"oauth2"}

The correct "scopes" should be "scopes": [
"email",
"phone",
"address"
], not ["email, phone, address"].

It seems something wrong with the OAuth 2.0 plugins.
The version of kong is 1.0.0

How to generate tokens

thanks for the great tutorial.
I have one question.
I run your code and saw finally tokens is generated.
how does this token is generated? Does this plugin use a special service (Auth2 provider) to generate tokens?

Update for Kong CE 0.14?

Any plans to update this for Kong CE 0.14 to use /services instead of /apis? I've gotten this working myself and would be happy to submit a PR with the changes to the app.js code and README.md

[Needs clarification] - Creating oauth2 application: redirect_uris <===> redirect_uri

Hey there !

I'm just wondering why when we create an oauth2 application we should specify an array of redirect uri (via the property redirect_uris) and once we claim for a code (via https://kong_host/oauth2/authorize/) we got in response only the first uri of the saved redirect_uris

{
    "redirect_uri": "http://my.first.redirect.uri?code=m3kUaBX3KyYslmrXMtvQV99RroarT79u"
}

So why should we pass an array if only one of them is returned ?

If anybody has an answer I would appreciate a lot !

Cheers

TypeError: Cannot read property 'length' of undefined

Hi there,

i have tried to implement oauth2 using this repo.

Everything went well till run node application with below command

node app.js

But when we hit browser below command
http://127.0.0.1:3000/authorize?response_type=code&scope=email%20address&client_id=wHsY4YI6K7gn2bYhsgPv4HB8Sw9bZ0JV
(client_id=wHsY4YI6K7gn2bYhsgPv4HB8Sw9bZ0JV : generated while creating client application)

we get this error: TypeError: Cannot read property 'length' of undefined

i have even tried this url in browser as well

http://127.0.0.1:3000/authorize?response_type=code&[email protected]&client_id=wHsY4YI6K7gn2bYhsgPv4HB8Sw9bZ0JV

gettting same error.

Check below stack-trace

osboxes@osboxes:~/kong-oauth2-hello-world$ node app.js 
PROVISION_KEY is xE4QYq1PiW6L5645Y9u52xiP5Qu3jLUR
SERVICE_HOST is mockbin.org
KONG_ADMIN is http://127.0.0.1:8001
KONG_API is https://127.0.0.1:8443
API_PATH is /mock
SCOPES is {   "email": "Grant permissions to read your email address",   "address": "Grant permissions to read your address information",   "phone": "Grant permissions to read your mobile phone number" }
Running at Port 3000
/home/osboxes/kong-oauth2-hello-world/app.js:70
      if (json_response.data.length == 1) {
                             ^

TypeError: Cannot read property 'length' of undefined
    at Request._callback (/home/osboxes/kong-oauth2-hello-world/app.js:70:30)
    at Request.self.callback (/home/osboxes/kong-oauth2-hello-world/node_modules/request/request.js:197:22)
    at emitTwo (events.js:126:13)
    at Request.emit (events.js:214:7)
    at Request.<anonymous> (/home/osboxes/kong-oauth2-hello-world/node_modules/request/request.js:1050:14)
    at emitOne (events.js:121:20)
    at Request.emit (events.js:211:7)
    at IncomingMessage.<anonymous> (/home/osboxes/kong-oauth2-hello-world/node_modules/request/request.js:996:12)
    at emitNone (events.js:111:20)
    at IncomingMessage.emit (events.js:208:7)

How to resolve this error

Thanks & regards

Does the oauth plugin work with routes (as opposed to apis)?

I've gone through the example using apis (and it works), but I can't get it to work with routes. For example, I have a service with a /foo route. The resulting authorize endpoint is then /foo/oauth2/authorize and I get a "no route and no API found with those values" message. I'm guessing I'm using the wrong route because the service works fine when not using the oauth plugin.

Access Denied: You must use HTTPS

I keep getting the following error:

{
  "error_description": "You must use HTTPS",
  "error":"access_denied"
}

Is there any way to disable SSL for testing in development?

example problem with kong version 0.11.1 (running in docker ce version 17.09.0-ce-mac35 (19611) on macOS 10.13.1)

I have followed the example step by step.

It work well until I click the "Authorize" button in browser, kong redirect my browser to http://getkong.org with code like in the example.

http://getkong.org/?code=e3YgIGs1TPJqKYAZJStcjaOCiqfumAfP

next step I will acquire access token with (note: I have changed client_id, client_secret and code to my configuration information)

curl https://127.0.0.1:8443/oauth2/token
-H "Host: test.com"
-d "grant_type=authorization_code"
-d "client_id=li4Th0DMMe28cgTQ1jSP6hsLvQMTiSbf"
-d "client_secret=LSVbkvq9943LbVW1NBANCbtgOEGJ3cNV"
-d "redirect_uri=http://getkong.org/"
-d "code=e3YgIGs1TPJqKYAZJStcjaOCiqfumAfP" --insecure

I expect kong should response access token in json format but I got
{"error_description":"Invalid code","error":"invalid_request"}

I have tried to remove -H "Host: test.com" and I got
curl https://127.0.0.1:8443/oauth2/token
-d "grant_type=authorization_code"
-d "client_id=li4Th0DMMe28cgTQ1jSP6hsLvQMTiSbf"
-d "client_secret=LSVbkvq9943LbVW1NBANCbtgOEGJ3cNV"
-d "redirect_uri=http://getkong.org/"
-d "code=e3YgIGs1TPJqKYAZJStcjaOCiqfumAfP" --insecure
{"message":"no API found with those values"}

I stuck at this point for 2-3 days. I don't know how to fix it.

Please note that I have successfully configured basic authentication and key authentication but oAuth2 plug-in.

After clicking the "Authorize" button, the server error, can be not redirected to the redirect_uri

undefined:1

^

SyntaxError: Unexpected token <
at Object.parse (native)
at Request._callback (/home/azureuser/kong-oauth2-hello-world/app.js:87:19)
at Request.self.callback (/home/azureuser/kong-oauth2-hello-world/node_modules/request/request.js:197:22)
at emitTwo (events.js:87:13)
at Request.emit (events.js:172:7)
at Request. (/home/azureuser/kong-oauth2-hello-world/node_modules/request/request.js:1050:14)
at emitOne (events.js:82:20)
at Request.emit (events.js:169:7)
at IncomingMessage. (/home/azureuser/kong-oauth2-hello-world/node_modules/request/request.js:996:12)
at emitNone (events.js:72:20)

Error: Invalid client_id

I cannot get this tutorial to work. Running through the steps after installing Kong from kong-free-trials-enterprise-edition-0.34-1.tar.gz, I get

Invalid client_id

from the browser after following the steps

FOO=<my kong server fqdn>
 ...
$ curl -X POST \
>   --url "http://$FOO:8001/services/mock-service/routes" \
>   --data 'hosts[]=mockbin.org' \
>   --data 'paths[]=/mock'
{"created_at":1551992655,"strip_path":true,"hosts":["mockbin.org"],"preserve_host":false,"regex_priority":0,"updated_at":1551992655,"paths":["\/mock"],"service":{"id":"77e96dbb-2783-46c7-997b-12290d0ccbfa"},"methods":null,"protocols":["http","https"],"id":"ad1ff79e-f223-483f-bebc-f80959013d63"}
$ curl -X POST \
>   --url "http://$FOO:8001/consumers/thefosk/oauth2/" \
>   --data "name=Hello World App" \
>   --data "redirect_uri=http://konghq.com/"
{"client_id":"sOSepVNXCwad89DKFN2fCtEHnUZIy8EX","created_at":1551992762000,"id":"bdd3ee02-9288-42b3-92ac-aad3ac42f67a","redirect_uri":["http:\/\/konghq.com\/"],"name":"Hello World App","client_secret":"KuS9eoDudoEFl3EHQ4uLsETr5MdltKAj","consumer_id":"84a57f2e-645d-4022-b2f3-19a156681b22"}
$ export LISTEN_PORT=3002
$ node app.js
PROVISION_KEY is zQSEvAeah4xDcarDDP7W7rqUNoAAR39M
SERVICE_HOST is mockbin.org
KONG_ADMIN is http//kong.eng.splunkdev.com:8001
KONG_API is https://kong.eng.splunkdev.com:8443
API_PATH is /mock
SCOPES is {   "email": "Grant permissions to read your email address",   "address": "Grant permissions to read your address information",   "phone": "Grant permissions to read your mobile phone number" }
Running at Port 3002

and copying the client_id from that last curl command into the browser bar thus:

http://localhost:3002/authorize?response_type=code&scope=email%20address&client_id=sOSepVNXCwad89DKFN2fCtEHnUZIy8EX

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.