Permalink
Browse files

Added the option to use basic HTTP authorization when making the API

calls
  • Loading branch information...
gkostov committed Jun 8, 2012
1 parent 8e408c2 commit 3927c9701b8d05f22bba4e75e9a0ad067fa2b1ec
Showing with 42 additions and 24 deletions.
  1. +7 −1 app.js
  2. +4 −2 public/javascripts/docs.js
  3. +31 −21 views/api.jade
View
8 app.js
@@ -465,7 +465,8 @@ function processRequest(req, res, next) {
// Unsecured API Call helper
function unsecuredCall() {
- console.log('Unsecured Call');
+ console.log('Unsecured Call:');
+// console.dir(reqQuery);
// Add API Key to params, if any.
if (apiKey != '' && apiKey != 'undefined' && apiKey != undefined) {
@@ -478,6 +479,11 @@ function processRequest(req, res, next) {
options.path += apiConfig.keyParam + '=' + apiKey;
}
+ // Perform signature routine, if any.
+ if (apiConfig.auth=='basicAuth') {
+ options.headers['Authorization']='Basic '+new Buffer(reqQuery.apiUsername+':'+reqQuery.apiPassword).toString('base64');
+ }
+
// Perform signature routine, if any.
if (apiConfig.signature) {
if (apiConfig.signature.type == 'signed_md5') {
@@ -173,9 +173,11 @@
var params = $(this).serializeArray(),
apiKey = { name: 'apiKey', value: $('input[name=key]').val() },
apiSecret = { name: 'apiSecret', value: $('input[name=secret]').val() },
- apiName = { name: 'apiName', value: $('input[name=apiName]').val() };
+ apiName = { name: 'apiName', value: $('input[name=apiName]').val() },
+ apiUsername = { name: 'apiUsername', value: $('input[name=username]').val() },
+ apiPassword = { name: 'apiPassword', value: $('input[name=password]').val() };
- params.push(apiKey, apiSecret, apiName);
+ params.push(apiKey, apiSecret, apiName, apiUsername, apiPassword);
// Setup results container
var resultContainer = $('.result', self);
View
@@ -14,30 +14,40 @@ form#credentials
img(src='/images/accept.png')
- else
h2 API Credentials
- img(src='/images/key.png')
+ img(src='/images/key.png')
- - if (apiInfo.oauth)
- input(type='hidden', name='oauth', value='authrequired')
-
- - if (apiInfo.auth.defaultKey)
- - var defaultKey =apiInfo.auth.defaultKey
- - else
- - var defaultKey =''
-
- - if (apiInfo.auth.defaultSecret)
- - var defaultSecret =apiInfo.auth.defaultSecret
+ - if(apiInfo.auth == 'basicAuth')
+ div (basic HTTP authorization)
+ br
+ div
+ label(for='key') User name
+ input(id='username', name='username', style='color=#EEEEEE')
+ div
+ label(for='key') Password
+ input(id='password', name='password', value=defaultKey, style='color=#EEEEEE')
- else
- - var defaultSecret =''
- div
- label(for='key') API Key
- input(id='key', name='key', value=defaultKey, style='color=#EEEEEE')
- div
- - if (apiInfo.oauth || apiInfo.signature)
- label(for='secret') Shared Secret
- input(id='secret', name='secret', value=defaultSecret, style='color=#EEEEEE')
- - if (apiInfo.oauth && apiInfo.oauth.type !='two-legged')
+ - if (apiInfo.oauth)
+ input(type='hidden', name='oauth', value='authrequired')
+
+ - if (apiInfo.auth.defaultKey)
+ - var defaultKey =apiInfo.auth.defaultKey
+ - else
+ - var defaultKey =''
+
+ - if (apiInfo.auth.defaultSecret)
+ - var defaultSecret =apiInfo.auth.defaultSecret
+ - else
+ - var defaultSecret =''
+ div
+ label(for='key') API Key
+ input(id='key', name='key', value=defaultKey, style='color=#EEEEEE')
div
- input(name='oauth', value='Authenticate with OAuth', type='submit', id='oauth-auth')
+ - if (apiInfo.oauth || apiInfo.signature)
+ label(for='secret') Shared Secret
+ input(id='secret', name='secret', value=defaultSecret, style='color=#EEEEEE')
+ - if (apiInfo.oauth && apiInfo.oauth.type !='two-legged')
+ div
+ input(name='oauth', value='Authenticate with OAuth', type='submit', id='oauth-auth')
div(id='controls')
ul

1 comment on commit 3927c97

@mansilladev

This comment has been minimized.

Show comment Hide comment
@mansilladev

mansilladev Sep 20, 2012

Thanks for the contrib. Basic auth is definitely something I/O Docs needs.

  • We should consider making "auth" an object that can contain multiple authorization schemes, instead of there only being one possible authorization config. It's not uncommon that we have clients that require both API key and basic auth.
  • For Basic auth, do you have any thoughts as to whether the configuration should address where the username and password values are obtained -- e.g. very top, where the API key/secret inputs are located, to be applied to every single resource/method, OR by parameter name, so that methods that have parameters names that match, the user/pass values will come from the form values on each individual method.

Example 1 - "auth" block is an object containing authorization scheme objects. In the "basicAuth" object below, there are no values, thus, the default behavior would be to render a view that has username/password input fields at the top (adjacent to the API key/secret fields) -- and these values would apply to every resource/method. Also in this example, note the "key" authorization object is moved under the "auth" object, and how "keyParam" is now "param".

      "phgsandbox": {
        "name": "Performance Horizon API (Sandbox)",
        "protocol": "http",
        "baseURL": "stagingapi.performancehorizon.com",
        "publicPath": "",
        "privatePath": "",
        "auth": {
             "basicAuth": {

             },
             "key": {
                   "param": "api_key"
             }
         ],
    }

Example 2 - Just like the example above, but the "username" and "password" keys are in the "basicAuth" block with parameter names defined -- meaning that the basic auth will pull the user/pass values from the method inputs for parameter names that match "username->param" and "password->param".

      "phgsandbox": {
        "name": "Performance Horizon API (Sandbox)",
        "protocol": "http",
        "baseURL": "stagingapi.performancehorizon.com",
        "publicPath": "",
        "privatePath": "",
        "auth": {
             "basicAuth": {
                  "username": {
                      "param": "accountName"
                  }
                  "password": {
                      "param": "accountPass"
                  }
             },
             "key": {
                   "param": "api_key"
             }
         ],
    }

Example 2.1 - The method configuration would look like this (to complement Example 2 basic auth schema convention above):

{
    "endpoints": [
        {
            "name": "Rockin Resources",
            "methods": [
                {
                    "MethodName": "The Foo Method",
                    "Synopsis": "A method that requires basic auth, as well as API key authentication",
                    "HTTPMethod": "GET",
                    "URI": "/foo",
                    "RequiresOAuth": "N",
                    "parameters": [
                        {
                            "Name": "accountName",
                            "Required": "Y",
                            "Default": "",
                            "Type": "string",
                            "Description": "Username, used in basic authorization"
                        },
                        {
                            "Name": "accountPass",
                            "Required": "Y",
                            "Default": "",
                            "Type": "string",
                            "Description": "Password, used in basic authorization"
                        },
                        {
                            "Name": "bar",
                            "Required": "N",
                            "Default": "12345",
                            "Type": "int",
                            "Description": "Just another arbitrary parameter for this method"
                        }
                }
               .......

Please share your thoughts.

p.s. the object/key naming in the examples are not ideas in stone -- clearly, there needs to be some cleanup around these conventions.. e.g. "sigParam", "keyParam", etc.

p.p.s. and yes, even the use of arrays vs. nested objects is worth a discussion. :)

Thanks for the contrib. Basic auth is definitely something I/O Docs needs.

  • We should consider making "auth" an object that can contain multiple authorization schemes, instead of there only being one possible authorization config. It's not uncommon that we have clients that require both API key and basic auth.
  • For Basic auth, do you have any thoughts as to whether the configuration should address where the username and password values are obtained -- e.g. very top, where the API key/secret inputs are located, to be applied to every single resource/method, OR by parameter name, so that methods that have parameters names that match, the user/pass values will come from the form values on each individual method.

Example 1 - "auth" block is an object containing authorization scheme objects. In the "basicAuth" object below, there are no values, thus, the default behavior would be to render a view that has username/password input fields at the top (adjacent to the API key/secret fields) -- and these values would apply to every resource/method. Also in this example, note the "key" authorization object is moved under the "auth" object, and how "keyParam" is now "param".

      "phgsandbox": {
        "name": "Performance Horizon API (Sandbox)",
        "protocol": "http",
        "baseURL": "stagingapi.performancehorizon.com",
        "publicPath": "",
        "privatePath": "",
        "auth": {
             "basicAuth": {

             },
             "key": {
                   "param": "api_key"
             }
         ],
    }

Example 2 - Just like the example above, but the "username" and "password" keys are in the "basicAuth" block with parameter names defined -- meaning that the basic auth will pull the user/pass values from the method inputs for parameter names that match "username->param" and "password->param".

      "phgsandbox": {
        "name": "Performance Horizon API (Sandbox)",
        "protocol": "http",
        "baseURL": "stagingapi.performancehorizon.com",
        "publicPath": "",
        "privatePath": "",
        "auth": {
             "basicAuth": {
                  "username": {
                      "param": "accountName"
                  }
                  "password": {
                      "param": "accountPass"
                  }
             },
             "key": {
                   "param": "api_key"
             }
         ],
    }

Example 2.1 - The method configuration would look like this (to complement Example 2 basic auth schema convention above):

{
    "endpoints": [
        {
            "name": "Rockin Resources",
            "methods": [
                {
                    "MethodName": "The Foo Method",
                    "Synopsis": "A method that requires basic auth, as well as API key authentication",
                    "HTTPMethod": "GET",
                    "URI": "/foo",
                    "RequiresOAuth": "N",
                    "parameters": [
                        {
                            "Name": "accountName",
                            "Required": "Y",
                            "Default": "",
                            "Type": "string",
                            "Description": "Username, used in basic authorization"
                        },
                        {
                            "Name": "accountPass",
                            "Required": "Y",
                            "Default": "",
                            "Type": "string",
                            "Description": "Password, used in basic authorization"
                        },
                        {
                            "Name": "bar",
                            "Required": "N",
                            "Default": "12345",
                            "Type": "int",
                            "Description": "Just another arbitrary parameter for this method"
                        }
                }
               .......

Please share your thoughts.

p.s. the object/key naming in the examples are not ideas in stone -- clearly, there needs to be some cleanup around these conventions.. e.g. "sigParam", "keyParam", etc.

p.p.s. and yes, even the use of arrays vs. nested objects is worth a discussion. :)

Please sign in to comment.