Authentication and Apps Script

Hello,
I am trying to connect to the Forms API through Google Apps Script and
can’t seem to get through authentication. Any help would be great. This is
what I am currently attempting to use:

function getFormInfo(formName) {

//If not set, set name to Client_Visits_20130726 for testing.
var settings, formName = formName || ‘[form_id]’;

settings = {
user: ‘[user]’,
module: ‘[module]’,
password: ‘[password]’,
form: formName,
base: ‘https://www.commcarehq.org/a/’,
headers: {
contentType: ‘application/json’,
headers: {
Authorization: ‘’
},
validateHttpsCertificates: false,
muteHttpExceptions: true
}
};

settings.url = settings.base + settings.module + ‘/api/v0.5/form/’ +
settings.form ;
settings.headers.headers.Authorization = 'Basic ’ +
Utilities.base64Encode(settings.user + ‘:’ + settings.password);
return settings;
}

Thanks,
Brendan

Hi Brendan,

Have you been able to successfully authenticate via the equivalent curl
command with the same user/module/password?

Are you getting any additional information in the response?

thanks,
Cory

··· On Mon, Sep 29, 2014 at 5:25 PM, Brendan Small wrote:

Hello,
I am trying to connect to the Forms API through Google Apps Script and
can’t seem to get through authentication. Any help would be great. This is
what I am currently attempting to use:

function getFormInfo(formName) {

//If not set, set name to Client_Visits_20130726 for testing.
var settings, formName = formName || ‘[form_id]’;

settings = {
user: ‘[user]’,
module: ‘[module]’,
password: ‘[password]’,
form: formName,
base: ‘https://www.commcarehq.org/a/’,
headers: {
contentType: ‘application/json’,
headers: {
Authorization: ‘’
},
validateHttpsCertificates: false,
muteHttpExceptions: true
}
};

settings.url = settings.base + settings.module + ‘/api/v0.5/form/’ +
settings.form ;
settings.headers.headers.Authorization = 'Basic ’ +
Utilities.base64Encode(settings.user + ‘:’ + settings.password);
return settings;
}

Thanks,
Brendan


You received this message because you are subscribed to the Google Groups
"CommCare Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to commcare-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Hi Brendan,

I did something similar for Formhub. Make sure you run the URL fetch
command within the UrlFetchApp.fetch() function. Test the basic
authentication with www.hurl.it to see if you can at least authenticate
then try it in GAS.

This repo
https://github.com/craigappl/Access_Formhub_From_Google_Apps_Script/blob/master/Authentication/Basic_Authentication_code.gs
is for formhub, but may be helpful for GAS interaction with CommCare.

There's also a working example
https://github.com/craigappl/Access_Formhub_From_Google_Apps_Script/blob/master/Working_Examples/Update_Spreadsheet
of pulling all data in to a spreadsheet. Again, this is for formhub, but
may be helpful for you :slight_smile:

Please post an update when you get it working!

Sincerely,
Craig

··· On Tuesday, September 30, 2014 3:10:53 AM UTC+5:45, Brendan Small wrote: > > Hello, > I am trying to connect to the Forms API through Google Apps Script and > can't seem to get through authentication. Any help would be great. This is > what I am currently attempting to use: > > function getFormInfo(formName) { > > //If not set, set name to Client_Visits_20130726 for testing. > var settings, formName = formName || '[form_id]'; > > settings = { > user: '[user]', > module: '[module]', > password: '[password]', > form: formName, > base: 'https://www.commcarehq.org/a/', > headers: { > contentType: 'application/json', > headers: { > Authorization: '' > }, > validateHttpsCertificates: false, > muteHttpExceptions: true > } > }; > > settings.url = settings.base + settings.module + '/api/v0.5/form/' + > settings.form ; > settings.headers.headers.Authorization = 'Basic ' + > Utilities.base64Encode(settings.user + ':' + settings.password); > return settings; > } > > Thanks, > Brendan >

Hi Cory,

I’m working with Brendan on this issue and can give you more information if
you need it.

It looks like the only API authentication method available is via Digest
Authentication. Is that the case? If so, may I ask why? Digest Auth is
difficult, to say the least, with JavaScript and, as we’re finding, near
impossible with Apps Script.

We’d like the opportunity to speak to someone regarding this issue as one
of the reasons that we’re actually paying for an account is to gain access
to the API.

Thanks,
Dave

··· On Monday, September 29, 2014 5:30:16 PM UTC-4, Cory Zue wrote: > > Hi Brendan, > > Have you been able to successfully authenticate via the equivalent curl > command with the same user/module/password? > > Are you getting any additional information in the response? > > thanks, > Cory > > On Mon, Sep 29, 2014 at 5:25 PM, Brendan Small <airs....@gmail.com > wrote: > >> Hello, >> I am trying to connect to the Forms API through Google Apps Script and >> can't seem to get through authentication. Any help would be great. This is >> what I am currently attempting to use: >> >> function getFormInfo(formName) { >> >> //If not set, set name to Client_Visits_20130726 for testing. >> var settings, formName = formName || '[form_id]'; >> >> settings = { >> user: '[user]', >> module: '[module]', >> password: '[password]', >> form: formName, >> base: 'https://www.commcarehq.org/a/', >> headers: { >> contentType: 'application/json', >> headers: { >> Authorization: '' >> }, >> validateHttpsCertificates: false, >> muteHttpExceptions: true >> } >> }; >> >> settings.url = settings.base + settings.module + '/api/v0.5/form/' >> + settings.form ; >> settings.headers.headers.Authorization = 'Basic ' + >> Utilities.base64Encode(settings.user + ':' + settings.password); >> return settings; >> } >> >> Thanks, >> Brendan >> >> -- >> >> --- >> You received this message because you are subscribed to the Google Groups >> "CommCare Developers" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to commcare-developers+unsubscribe@googlegroups.com . >> For more options, visit https://groups.google.com/d/optout. >> > >

Hi Dave,

We can likely extend the APIs to support basic authentication. Which APIs
are you using? Feel free to email commcarehq-support@dimagi.com with your
exact request and someone on our team will follow up.

thanks,
Cory

··· On Wed, Oct 1, 2014 at 9:05 AM, Dave Greene wrote:

Hi Cory,

I’m working with Brendan on this issue and can give you more information
if you need it.

It looks like the only API authentication method available is via Digest
Authentication. Is that the case? If so, may I ask why? Digest Auth is
difficult, to say the least, with JavaScript and, as we’re finding, near
impossible with Apps Script.

We’d like the opportunity to speak to someone regarding this issue as one
of the reasons that we’re actually paying for an account is to gain access
to the API.

Thanks,
Dave

On Monday, September 29, 2014 5:30:16 PM UTC-4, Cory Zue wrote:

Hi Brendan,

Have you been able to successfully authenticate via the equivalent curl
command with the same user/module/password?

Are you getting any additional information in the response?

thanks,
Cory

On Mon, Sep 29, 2014 at 5:25 PM, Brendan Small airs....@gmail.com wrote:

Hello,
I am trying to connect to the Forms API through Google Apps Script and
can’t seem to get through authentication. Any help would be great. This is
what I am currently attempting to use:

function getFormInfo(formName) {

//If not set, set name to Client_Visits_20130726 for testing.
var settings, formName = formName || ‘[form_id]’;

settings = {
user: ‘[user]’,
module: ‘[module]’,
password: ‘[password]’,
form: formName,
base: ‘https://www.commcarehq.org/a/’,
headers: {
contentType: ‘application/json’,
headers: {
Authorization: ‘’
},
validateHttpsCertificates: false,
muteHttpExceptions: true
}
};

settings.url = settings.base + settings.module + ‘/api/v0.5/form/’

  • settings.form ;
    settings.headers.headers.Authorization = 'Basic ’ +
    Utilities.base64Encode(settings.user + ‘:’ + settings.password);
    return settings;
    }

Thanks,
Brendan


You received this message because you are subscribed to the Google
Groups “CommCare Developers” group.
To unsubscribe from this group and stop receiving emails from it, send
an email to commcare-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


You received this message because you are subscribed to the Google Groups
"CommCare Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to commcare-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Hi Cory,

I’ll get in touch with commcarehq support, but just to provide more
information here in case anyone searches for this issue:

We’re using Google Apps Script and, because it’s JavaScript-ish, we’re
rolling our own call and response process to implement Digest Auth.
Basically the process is this:

  1. Send a request to the API for a specific resource
  2. Capture returned headers (the WWW-Authenticate one, specifically.)
    The following are provided by the CommcareHQ server:
  • nonce
    • realm
    • algorithm
    • opaque
    • qop
    • stale
    1. Following the Digest Auth spec, we generate HA1 by MD5 hashing
      "username:realm:password" then converting the returned bytes to hex
  1. Generate HA2 by MD5 hashing “request_type:uri” then converting the
    returned bytes to hex
  2. Generate *response *by MD5 hashing
    "HA1:nonce:nonce_count:cnonce:qop:HA2" then converting the returned bytes
    to hex.
    • nonce_count is an arbitrary value that we set at “00000001”. I’ve
      confirmed this is fine by running the same request via CURL and examining
      the headers.
    • cnonce is generated by Date().getTime().toString(16). From my
      reading, cnonce only needs to be a uniquely supplied value from the client.
  3. Construct the “Authorization” header:
    • Digest username=“username”, realm="[supplied by server]",
      nonce="[supplied by server]", uri=“uri”, cnonce=“cnonce”, nc=
      nc, qop="[supplied by server]", response=“response”, algorithm="[supplied
      by server]
      "
    • The text in bold (especially uri, cnonce, nc, and response) are
      references to variables discussed above.
  4. Send the request to the API for the same resource with the generated
    Authorization header
  5. This is where we’d expect a 200 response with the requested data.
    When using the exact same headers in CURL, it works. Instead we get the
    same 401.

Obviously there’s an issue with either MD5 hashing on our end, the cnonce
being interpreted on your end, or something else in the handshake on your
end.

Basic Auth is absolutely the preferable method for us, so adding it to the
API would be great.

Thanks,
Dave

··· On Wednesday, October 1, 2014 9:59:25 AM UTC-4, Cory Zue wrote: > > Hi Dave, > > We can likely extend the APIs to support basic authentication. Which APIs > are you using? Feel free to email commcarehq-support@dimagi.com with your > exact request and someone on our team will follow up. > > thanks, > Cory > > > On Wed, Oct 1, 2014 at 9:05 AM, Dave Greene >> Hi Cory, >> >> I'm working with Brendan on this issue and can give you more information >> if you need it. >> >> It looks like the only API authentication method available is via Digest >> Authentication. Is that the case? If so, may I ask why? Digest Auth is >> difficult, to say the least, with JavaScript and, as we're finding, near >> impossible with Apps Script. >> >> We'd like the opportunity to speak to someone regarding this issue as one >> of the reasons that we're actually paying for an account is to gain access >> to the API. >> >> Thanks, >> Dave >> >> On Monday, September 29, 2014 5:30:16 PM UTC-4, Cory Zue wrote: >>> >>> Hi Brendan, >>> >>> Have you been able to successfully authenticate via the equivalent curl >>> command with the same user/module/password? >>> >>> Are you getting any additional information in the response? >>> >>> thanks, >>> Cory >>> >>> On Mon, Sep 29, 2014 at 5:25 PM, Brendan Small wrote: >>> >>>> Hello, >>>> I am trying to connect to the Forms API through Google Apps Script and >>>> can't seem to get through authentication. Any help would be great. This is >>>> what I am currently attempting to use: >>>> >>>> function getFormInfo(formName) { >>>> >>>> //If not set, set name to Client_Visits_20130726 for testing. >>>> var settings, formName = formName || '[form_id]'; >>>> >>>> settings = { >>>> user: '[user]', >>>> module: '[module]', >>>> password: '[password]', >>>> form: formName, >>>> base: 'https://www.commcarehq.org/a/', >>>> headers: { >>>> contentType: 'application/json', >>>> headers: { >>>> Authorization: '' >>>> }, >>>> validateHttpsCertificates: false, >>>> muteHttpExceptions: true >>>> } >>>> }; >>>> >>>> settings.url = settings.base + settings.module + >>>> '/api/v0.5/form/' + settings.form ; >>>> settings.headers.headers.Authorization = 'Basic ' + >>>> Utilities.base64Encode(settings.user + ':' + settings.password); >>>> return settings; >>>> } >>>> >>>> Thanks, >>>> Brendan >>>> >>>> -- >>>> >>>> --- >>>> You received this message because you are subscribed to the Google >>>> Groups "CommCare Developers" group. >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to commcare-developers+unsubscribe@googlegroups.com. >>>> For more options, visit https://groups.google.com/d/optout. >>>> >>> >>> -- >> >> --- >> You received this message because you are subscribed to the Google Groups >> "CommCare Developers" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to commcare-developers+unsubscribe@googlegroups.com. >> For more options, visit https://groups.google.com/d/optout. >> > >

Hi Dave,

Thanks. We got your ticket and will follow up soon after we’ve had a chance
to scope out basic auth.

best,
Cory

··· On Wed, Oct 1, 2014 at 2:04 PM, Dave Greene wrote:

Hi Cory,

I’ll get in touch with commcarehq support, but just to provide more
information here in case anyone searches for this issue:

We’re using Google Apps Script and, because it’s JavaScript-ish, we’re
rolling our own call and response process to implement Digest Auth.
Basically the process is this:

  1. Send a request to the API for a specific resource
  2. Capture returned headers (the WWW-Authenticate one, specifically.)
    The following are provided by the CommcareHQ server:
  • nonce
    • realm
    • algorithm
    • opaque
    • qop
    • stale
    1. Following the Digest Auth spec, we generate HA1 by MD5 hashing
      "username:realm:password" then converting the returned bytes to hex
  1. Generate HA2 by MD5 hashing “request_type:uri” then converting
    the returned bytes to hex
  2. Generate *response *by MD5 hashing
    "HA1:nonce:nonce_count:cnonce:qop:HA2" then converting the returned bytes
    to hex.
    • nonce_count is an arbitrary value that we set at “00000001”. I’ve
      confirmed this is fine by running the same request via CURL and examining
      the headers.
    • cnonce is generated by Date().getTime().toString(16). From my
      reading, cnonce only needs to be a uniquely supplied value from the client.
  3. Construct the “Authorization” header:
    • Digest username=“username”, realm="[supplied by server]",
      nonce="[supplied by server]", uri=“uri”, cnonce=“cnonce”, nc=
      nc, qop="[supplied by server]", response=“response”,
      algorithm="[supplied by server]"
    • The text in bold (especially uri, cnonce, nc, and response) are
      references to variables discussed above.
  4. Send the request to the API for the same resource with the
    generated Authorization header
  5. This is where we’d expect a 200 response with the requested data.
    When using the exact same headers in CURL, it works. Instead we get the
    same 401.

Obviously there’s an issue with either MD5 hashing on our end, the cnonce
being interpreted on your end, or something else in the handshake on your
end.

Basic Auth is absolutely the preferable method for us, so adding it to the
API would be great.

Thanks,
Dave

On Wednesday, October 1, 2014 9:59:25 AM UTC-4, Cory Zue wrote:

Hi Dave,

We can likely extend the APIs to support basic authentication. Which APIs
are you using? Feel free to email commcarehq-support@dimagi.com with
your exact request and someone on our team will follow up.

thanks,
Cory

On Wed, Oct 1, 2014 at 9:05 AM, Dave Greene < david_bell-feins@abtassoc.com> wrote:

Hi Cory,

I’m working with Brendan on this issue and can give you more information
if you need it.

It looks like the only API authentication method available is via Digest
Authentication. Is that the case? If so, may I ask why? Digest Auth is
difficult, to say the least, with JavaScript and, as we’re finding, near
impossible with Apps Script.

We’d like the opportunity to speak to someone regarding this issue as
one of the reasons that we’re actually paying for an account is to gain
access to the API.

Thanks,
Dave

On Monday, September 29, 2014 5:30:16 PM UTC-4, Cory Zue wrote:

Hi Brendan,

Have you been able to successfully authenticate via the equivalent curl
command with the same user/module/password?

Are you getting any additional information in the response?

thanks,
Cory

On Mon, Sep 29, 2014 at 5:25 PM, Brendan Small airs....@gmail.com wrote:

Hello,
I am trying to connect to the Forms API through Google Apps Script and
can’t seem to get through authentication. Any help would be great. This is
what I am currently attempting to use:

function getFormInfo(formName) {

//If not set, set name to Client_Visits_20130726 for testing.
var settings, formName = formName || ‘[form_id]’;

settings = {
user: ‘[user]’,
module: ‘[module]’,
password: ‘[password]’,
form: formName,
base: ‘https://www.commcarehq.org/a/’,
headers: {
contentType: ‘application/json’,
headers: {
Authorization: ‘’
},
validateHttpsCertificates: false,
muteHttpExceptions: true
}
};

settings.url = settings.base + settings.module +
’/api/v0.5/form/’ + settings.form ;
settings.headers.headers.Authorization = 'Basic ’ +
Utilities.base64Encode(settings.user + ‘:’ + settings.password);
return settings;
}

Thanks,
Brendan


You received this message because you are subscribed to the Google
Groups “CommCare Developers” group.
To unsubscribe from this group and stop receiving emails from it, send
an email to commcare-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


You received this message because you are subscribed to the Google
Groups “CommCare Developers” group.
To unsubscribe from this group and stop receiving emails from it, send
an email to commcare-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


You received this message because you are subscribed to the Google Groups
"CommCare Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to commcare-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Hi Dave,

Thanks for this write up. Could you share your working version of the
script? I’ll get to testing on my end.

These are some rough ideas:

Sincerely,
Craig

··· On Wed, Oct 1, 2014 at 11:49 PM, Dave Greene wrote:

Hi Cory,

I’ll get in touch with commcarehq support, but just to provide more
information here in case anyone searches for this issue:

We’re using Google Apps Script and, because it’s JavaScript-ish, we’re
rolling our own call and response process to implement Digest Auth.
Basically the process is this:

  1. Send a request to the API for a specific resource
  2. Capture returned headers (the WWW-Authenticate one, specifically.)
    The following are provided by the CommcareHQ server:
  • nonce
    • realm
    • algorithm
    • opaque
    • qop
    • stale
    1. Following the Digest Auth spec, we generate HA1 by MD5 hashing
      "username:realm:password" then converting the returned bytes to hex
  1. Generate HA2 by MD5 hashing “request_type:uri” then converting
    the returned bytes to hex
  2. Generate *response *by MD5 hashing
    "HA1:nonce:nonce_count:cnonce:qop:HA2" then converting the returned bytes
    to hex.
    • nonce_count is an arbitrary value that we set at “00000001”. I’ve
      confirmed this is fine by running the same request via CURL and examining
      the headers.
    • cnonce is generated by Date().getTime().toString(16). From my
      reading, cnonce only needs to be a uniquely supplied value from the client.
  3. Construct the “Authorization” header:
    • Digest username=“username”, realm="[supplied by server]",
      nonce="[supplied by server]", uri=“uri”, cnonce=“cnonce”, nc=
      nc, qop="[supplied by server]", response=“response”,
      algorithm="[supplied by server]"
    • The text in bold (especially uri, cnonce, nc, and response) are
      references to variables discussed above.
  4. Send the request to the API for the same resource with the
    generated Authorization header
  5. This is where we’d expect a 200 response with the requested data.
    When using the exact same headers in CURL, it works. Instead we get the
    same 401.

Obviously there’s an issue with either MD5 hashing on our end, the cnonce
being interpreted on your end, or something else in the handshake on your
end.

Basic Auth is absolutely the preferable method for us, so adding it to the
API would be great.

Thanks,
Dave

On Wednesday, October 1, 2014 9:59:25 AM UTC-4, Cory Zue wrote:

Hi Dave,

We can likely extend the APIs to support basic authentication. Which APIs
are you using? Feel free to email commcarehq-support@dimagi.com with
your exact request and someone on our team will follow up.

thanks,
Cory

On Wed, Oct 1, 2014 at 9:05 AM, Dave Greene < david_bell-feins@abtassoc.com> wrote:

Hi Cory,

I’m working with Brendan on this issue and can give you more information
if you need it.

It looks like the only API authentication method available is via Digest
Authentication. Is that the case? If so, may I ask why? Digest Auth is
difficult, to say the least, with JavaScript and, as we’re finding, near
impossible with Apps Script.

We’d like the opportunity to speak to someone regarding this issue as
one of the reasons that we’re actually paying for an account is to gain
access to the API.

Thanks,
Dave

On Monday, September 29, 2014 5:30:16 PM UTC-4, Cory Zue wrote:

Hi Brendan,

Have you been able to successfully authenticate via the equivalent curl
command with the same user/module/password?

Are you getting any additional information in the response?

thanks,
Cory

On Mon, Sep 29, 2014 at 5:25 PM, Brendan Small airs....@gmail.com wrote:

Hello,
I am trying to connect to the Forms API through Google Apps Script and
can’t seem to get through authentication. Any help would be great. This is
what I am currently attempting to use:

function getFormInfo(formName) {

//If not set, set name to Client_Visits_20130726 for testing.
var settings, formName = formName || ‘[form_id]’;

settings = {
user: ‘[user]’,
module: ‘[module]’,
password: ‘[password]’,
form: formName,
base: ‘https://www.commcarehq.org/a/’,
headers: {
contentType: ‘application/json’,
headers: {
Authorization: ‘’
},
validateHttpsCertificates: false,
muteHttpExceptions: true
}
};

settings.url = settings.base + settings.module +
’/api/v0.5/form/’ + settings.form ;
settings.headers.headers.Authorization = 'Basic ’ +
Utilities.base64Encode(settings.user + ‘:’ + settings.password);
return settings;
}

Thanks,
Brendan


You received this message because you are subscribed to the Google
Groups “CommCare Developers” group.
To unsubscribe from this group and stop receiving emails from it, send
an email to commcare-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


You received this message because you are subscribed to the Google
Groups “CommCare Developers” group.
To unsubscribe from this group and stop receiving emails from it, send
an email to commcare-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


You received this message because you are subscribed to a topic in the
Google Groups “CommCare Developers” group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/commcare-developers/iHgVHw3Em5A/unsubscribe
.
To unsubscribe from this group and all its topics, send an email to
commcare-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Hi Craig,

Unfortunately the script doesn’t work, even though theoretically it should.

We are using Utilities.computeDigest() to calculate the MD5 hash.
Unfortunately it’s just not working. My guess is that there’s some kind of
issue between the way your application is expecting the digest response vs
the way that computeDigest() is calculating the hash.

I don’t have the time to dive too deeply into this issue, so my absolute
preference would be if you guys implemented basic auth.

Thanks,
Dave

··· On Thursday, October 2, 2014 12:47:15 AM UTC-4, Craig A. wrote: > > Hi Dave, > > Thanks for this write up. Could you share your working version of the > script? I'll get to testing on my end. > > These are some rough ideas: > - Are you using the computeDigest Utility > This > utility also has a character encoding extension. I don't know if this > should be UTF-8 as well. > - This isn't ideal, but you could use the form and case forwarding > in > CommCare to post the data to GAS. You would have to create a doPost(e) > function in GAS to receive the POST command and then XML.parse() to a > spreadsheet or HTML file on your Google Drive. If you go this route, you > have to allow your GAS to be run anonymously because there is no > authentication support for the case forwarding. > > Sincerely, > Craig > > On Wed, Oct 1, 2014 at 11:49 PM, Dave Greene <david_be...@abtassoc.com > wrote: > >> Hi Cory, >> >> I'll get in touch with commcarehq support, but just to provide more >> information here in case anyone searches for this issue: >> >> We're using Google Apps Script and, because it's JavaScript-ish, we're >> rolling our own call and response process to implement Digest Auth. >> Basically the process is this: >> >> 1. Send a request to the API for a specific resource >> 2. Capture returned headers (the WWW-Authenticate one, specifically.) >> The following are provided by the CommcareHQ server: >> - nonce >> - realm >> - algorithm >> - opaque >> - qop >> - stale >> 3. Following the Digest Auth spec, we generate *HA1* by MD5 >> hashing "username:realm:password" then converting the returned bytes to hex >> 4. Generate *HA2* by MD5 hashing "request_type:uri" then converting >> the returned bytes to hex >> 5. Generate *response *by MD5 hashing >> "HA1:nonce:nonce_count:cnonce:qop:HA2" then converting the returned bytes >> to hex. >> - nonce_count is an arbitrary value that we set at "00000001". >> I've confirmed this is fine by running the same request via CURL and >> examining the headers. >> - cnonce is generated by Date().getTime().toString(16). From my >> reading, cnonce only needs to be a uniquely supplied value from the client. >> 6. Construct the "Authorization" header: >> - Digest username="*username*", realm="*[supplied by server]*", >> nonce="*[supplied by server]*", uri="*uri*", cnonce="*cnonce*", nc= >> *nc*, qop="*[supplied by server]*", response="*response*", >> algorithm="*[supplied by server]*" >> - The text in bold (especially uri, cnonce, nc, and response) are >> references to variables discussed above. >> 7. Send the request to the API for the same resource with the >> generated Authorization header >> 8. This is where we'd expect a 200 response with the requested data. >> When using the exact same headers in CURL, it works. Instead we get the >> same 401. >> >> Obviously there's an issue with either MD5 hashing on our end, the cnonce >> being interpreted on your end, or something else in the handshake on your >> end. >> >> Basic Auth is absolutely the preferable method for us, so adding it to >> the API would be great. >> >> Thanks, >> Dave >> >> On Wednesday, October 1, 2014 9:59:25 AM UTC-4, Cory Zue wrote: >>> >>> Hi Dave, >>> >>> We can likely extend the APIs to support basic authentication. Which >>> APIs are you using? Feel free to email commcareh...@dimagi.com >>> with your exact request and someone on our team will >>> follow up. >>> >>> thanks, >>> Cory >>> >>> >>> On Wed, Oct 1, 2014 at 9:05 AM, Dave Greene <david_be...@abtassoc.com > wrote: >>> >>>> Hi Cory, >>>> >>>> I'm working with Brendan on this issue and can give you more >>>> information if you need it. >>>> >>>> It looks like the only API authentication method available is via >>>> Digest Authentication. Is that the case? If so, may I ask why? Digest Auth >>>> is difficult, to say the least, with JavaScript and, as we're finding, near >>>> impossible with Apps Script. >>>> >>>> We'd like the opportunity to speak to someone regarding this issue as >>>> one of the reasons that we're actually paying for an account is to gain >>>> access to the API. >>>> >>>> Thanks, >>>> Dave >>>> >>>> On Monday, September 29, 2014 5:30:16 PM UTC-4, Cory Zue wrote: >>>>> >>>>> Hi Brendan, >>>>> >>>>> Have you been able to successfully authenticate via the equivalent >>>>> curl command with the same user/module/password? >>>>> >>>>> Are you getting any additional information in the response? >>>>> >>>>> thanks, >>>>> Cory >>>>> >>>>> On Mon, Sep 29, 2014 at 5:25 PM, Brendan Small wrote: >>>>> >>>>>> Hello, >>>>>> I am trying to connect to the Forms API through Google Apps Script >>>>>> and can't seem to get through authentication. Any help would be great. This >>>>>> is what I am currently attempting to use: >>>>>> >>>>>> function getFormInfo(formName) { >>>>>> >>>>>> //If not set, set name to Client_Visits_20130726 for testing. >>>>>> var settings, formName = formName || '[form_id]'; >>>>>> >>>>>> settings = { >>>>>> user: '[user]', >>>>>> module: '[module]', >>>>>> password: '[password]', >>>>>> form: formName, >>>>>> base: 'https://www.commcarehq.org/a/', >>>>>> headers: { >>>>>> contentType: 'application/json', >>>>>> headers: { >>>>>> Authorization: '' >>>>>> }, >>>>>> validateHttpsCertificates: false, >>>>>> muteHttpExceptions: true >>>>>> } >>>>>> }; >>>>>> >>>>>> settings.url = settings.base + settings.module + >>>>>> '/api/v0.5/form/' + settings.form ; >>>>>> settings.headers.headers.Authorization = 'Basic ' + >>>>>> Utilities.base64Encode(settings.user + ':' + settings.password); >>>>>> return settings; >>>>>> } >>>>>> >>>>>> Thanks, >>>>>> Brendan >>>>>> >>>>>> -- >>>>>> >>>>>> --- >>>>>> You received this message because you are subscribed to the Google >>>>>> Groups "CommCare Developers" group. >>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>> send an email to commcare-developers+unsubscribe@googlegroups.com. >>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>> >>>>> >>>>> -- >>>> >>>> --- >>>> You received this message because you are subscribed to the Google >>>> Groups "CommCare Developers" group. >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to commcare-developers+unsubscribe@googlegroups.com >>>> . >>>> For more options, visit https://groups.google.com/d/optout. >>>> >>> >>> -- >> >> --- >> You received this message because you are subscribed to a topic in the >> Google Groups "CommCare Developers" group. >> To unsubscribe from this topic, visit >> https://groups.google.com/d/topic/commcare-developers/iHgVHw3Em5A/unsubscribe >> . >> To unsubscribe from this group and all its topics, send an email to >> commcare-developers+unsubscribe@googlegroups.com . >> For more options, visit https://groups.google.com/d/optout. >> > >

Hi Dave,

I’m pleased to announce that we just rolled out basic auth support for all
APIs. Let us know if you have any problems.

Cory

··· On Thu, Oct 2, 2014 at 10:40 AM, Dave Greene wrote:

Hi Craig,

Unfortunately the script doesn’t work, even though theoretically it should.

We are using Utilities.computeDigest() to calculate the MD5 hash.
Unfortunately it’s just not working. My guess is that there’s some kind of
issue between the way your application is expecting the digest response vs
the way that computeDigest() is calculating the hash.

I don’t have the time to dive too deeply into this issue, so my absolute
preference would be if you guys implemented basic auth.

Thanks,
Dave

On Thursday, October 2, 2014 12:47:15 AM UTC-4, Craig A. wrote:

Hi Dave,

Thanks for this write up. Could you share your working version of the
script? I’ll get to testing on my end.

These are some rough ideas:

Sincerely,
Craig

On Wed, Oct 1, 2014 at 11:49 PM, Dave Greene david_be...@abtassoc.com wrote:

Hi Cory,

I’ll get in touch with commcarehq support, but just to provide more
information here in case anyone searches for this issue:

We’re using Google Apps Script and, because it’s JavaScript-ish, we’re
rolling our own call and response process to implement Digest Auth.
Basically the process is this:

  1. Send a request to the API for a specific resource
  2. Capture returned headers (the WWW-Authenticate one,
    specifically.) The following are provided by the CommcareHQ server:
  • nonce
    • realm
    • algorithm
    • opaque
    • qop
    • stale
    1. Following the Digest Auth spec, we generate HA1 by MD5
      hashing “username:realm:password” then converting the returned bytes to hex
  1. Generate HA2 by MD5 hashing “request_type:uri” then converting
    the returned bytes to hex
  2. Generate *response *by MD5 hashing "HA1:nonce:nonce_count:cnonce:qop:HA2"
    then converting the returned bytes to hex.
    • nonce_count is an arbitrary value that we set at “00000001”.
      I’ve confirmed this is fine by running the same request via CURL and
      examining the headers.
    • cnonce is generated by Date().getTime().toString(16). From my
      reading, cnonce only needs to be a uniquely supplied value from the client.
  3. Construct the “Authorization” header:
    • Digest username=“username”, realm="[supplied by server]",
      nonce="[supplied by server]", uri=“uri”, cnonce=“cnonce”,
      nc=nc, qop="[supplied by server]", response=“response”,
      algorithm="[supplied by server]"
    • The text in bold (especially uri, cnonce, nc, and response) are
      references to variables discussed above.
  4. Send the request to the API for the same resource with the
    generated Authorization header
  5. This is where we’d expect a 200 response with the requested data.
    When using the exact same headers in CURL, it works. Instead we get the
    same 401.

Obviously there’s an issue with either MD5 hashing on our end, the
cnonce being interpreted on your end, or something else in the handshake on
your end.

Basic Auth is absolutely the preferable method for us, so adding it to
the API would be great.

Thanks,
Dave

On Wednesday, October 1, 2014 9:59:25 AM UTC-4, Cory Zue wrote:

Hi Dave,

We can likely extend the APIs to support basic authentication. Which
APIs are you using? Feel free to email commcareh...@dimagi.com with
your exact request and someone on our team will follow up.

thanks,
Cory

On Wed, Oct 1, 2014 at 9:05 AM, Dave Greene david_be...@abtassoc.com wrote:

Hi Cory,

I’m working with Brendan on this issue and can give you more
information if you need it.

It looks like the only API authentication method available is via
Digest Authentication. Is that the case? If so, may I ask why? Digest Auth
is difficult, to say the least, with JavaScript and, as we’re finding, near
impossible with Apps Script.

We’d like the opportunity to speak to someone regarding this issue as
one of the reasons that we’re actually paying for an account is to gain
access to the API.

Thanks,
Dave

On Monday, September 29, 2014 5:30:16 PM UTC-4, Cory Zue wrote:

Hi Brendan,

Have you been able to successfully authenticate via the equivalent
curl command with the same user/module/password?

Are you getting any additional information in the response?

thanks,
Cory

On Mon, Sep 29, 2014 at 5:25 PM, Brendan Small airs....@gmail.com wrote:

Hello,
I am trying to connect to the Forms API through Google Apps Script
and can’t seem to get through authentication. Any help would be great. This
is what I am currently attempting to use:

function getFormInfo(formName) {

//If not set, set name to Client_Visits_20130726 for testing.
var settings, formName = formName || ‘[form_id]’;

settings = {
user: ‘[user]’,
module: ‘[module]’,
password: ‘[password]’,
form: formName,
base: ‘https://www.commcarehq.org/a/’,
headers: {
contentType: ‘application/json’,
headers: {
Authorization: ‘’
},
validateHttpsCertificates: false,
muteHttpExceptions: true
}
};

settings.url = settings.base + settings.module +
’/api/v0.5/form/’ + settings.form ;
settings.headers.headers.Authorization = 'Basic ’ +
Utilities.base64Encode(settings.user + ‘:’ + settings.password);
return settings;
}

Thanks,
Brendan


You received this message because you are subscribed to the Google
Groups “CommCare Developers” group.
To unsubscribe from this group and stop receiving emails from it,
send an email to commcare-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


You received this message because you are subscribed to the Google
Groups “CommCare Developers” group.
To unsubscribe from this group and stop receiving emails from it, send
an email to commcare-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


You received this message because you are subscribed to a topic in the
Google Groups “CommCare Developers” group.
To unsubscribe from this topic, visit https://groups.google.com/d/
topic/commcare-developers/iHgVHw3Em5A/unsubscribe.
To unsubscribe from this group and all its topics, send an email to
commcare-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


You received this message because you are subscribed to the Google Groups
"CommCare Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to commcare-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.