Search code examples
apiauthenticationoauthkong

Need help about Kong and OAuth with self-managed user-database


I need to use Kong and OAuth to build a web app and some other APIs.


Now I have:

  • A server for Kong.
  • A server storages User Information such as id, username, password. Named it as User-Database.

I need to:

  • The web app and some others are going to use APIs with OAuth2.0;
  • APIs are provided by Kong only.

According to the document on Kong, I designed out a Resource Owner Password Credential one., and it is like this:

(These APIs are just for getting accessToken, no authentication method)

  1. User-End post Username&Password to Kong
  2. Kong routes it to User-Database.
  3. User-Database verifies the username and password, and post a request to Kong. The request will include username, password, provision_key, autherticated_userid. (*)
  4. Kong will response a access_token to User-Database, and will also remeber the autherticated_userid, access_token and scope. Kong will remeber them before the access-token expired.
  5. After User-Database received the response from Kong, it will response too for step 1 & 2, and finally the User-End will get the access-token for future use.

(Got the access-token)

  1. User-End is going to send request to APIs which need authentication.

enter image description here


There is something I couldn't understand at the step 3.

According to the document on Kong:

$ curl https://your.api.com/oauth2/token \ --header "Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW" \ --data "client_id=XXX" \ --data "client_secret=XXX" \ --data "scope=XXX" \ --data "provision_key=XXX" \ --data "authenticated_userid=XXX" \ --data "username=XXX" \ --data "password=XXX"

The provision_key is the key the plugin has generated when it has been added to the API, while authenticated_userid is the ID of the end user whose username and password belong to.

Should I storage all the users' information to my self-managed user-database and Kong both?

Or is there something I missed or I could optimizate ?

Link:Kong resource-owner-password-credentials


Solution

  • The documentation of Kong is rather misleading in terms of the Resource Owner Password Grant.

    This flow still needs you to implement an Authorization Server, of which the task is:

    • To authenticate the user, in this case using the provided username and password
    • To authorize the user, i.e. decide whether an access token should be issued, and decide on the scope

    Please note that both of these things are entirely up to you.

    Your Authorization Server in the end implements its own /authorize endpoint which should work like this:

    Your client app posts:

    client_id=<your client id>&
    client_secret=<your client secret>&
    username=<...>&
    password=<...>&
    grant_type=password&
    (optional: scope=space delimited scopes)
    

    Your authorization server keeps the provision_key or retrieves it via Kong Admin API (depending on how your architecture looks like and whether you can use the Admin API from your Auth Server).

    Then you can assemble the actual call to Kong's /oauth2/token end point using both the data from the Authorization Server (i.e. the authenticated user ID and the authenticated scope), the provision_key and the client credentials from your client application:

    POST https://kong:8443/yourapi/oauth2/token
    
    grant_type=password&
    client_id=(...)&
    client_secret=(...)&
    authenticated_userid=(...)&
    authenticated_scope=(...)&
    provision_key=(...)
    

    Please also note that it's crucial for the web app to be confidential in case you store the client ID and secret inside it, i.e. use the client secret only server side. For non-trusted applications (mobile, SPAs), it's possible to let the Authorization Server retrieve the client secret for use with Kong, via client ID to secret lookup (also using the Kong Admin API).