5

In vain I have tried to get OAuth 1.0 authentication working for Oracle Netsuite. When I generate the authentication header with PostMan it works, but my code, generates the wrong signature, despite the fact that I followed all the steps I could find on how to generate a HMAC-SHA1 signature for OAuth 1.0

Source code (Kotlin)

class NetsuiteAuthenticationScheme {

    private val algorithm = "HmacSHA1"
    private val charset = Charsets.UTF_8

    fun setAuthenticationHeaders(headers: HttpHeaders, url: String?) {

        val authentication = mutableMapOf(
                "realm" to "REALM",
                "oauth_consumer_key" to "CONSUMER_KEY",
                "oauth_token" to "TOKEN",
                "oauth_signature_method" to "HMAC-SHA1",
                "oauth_version" to "1.0",
                "oauth_timestamp" to "TIMESTAMP",
                "oauth_nonce" to "NONCE"
        )

        val signatureUrl = listOf(
                "POST",
                URLEncoder.encode(url, charset.displayName()),
                URLEncoder.encode(
                        URLEncodedUtils.format(
                                authentication
                                        .toList()
                                        .sortedBy { it.first }
                                        .map { BasicNameValuePair(it.first, it.second) },
                                charset.displayName()
                        ), charset.displayName()
                )
        ).joinToString("&")

        val signatureKey = listOf(
                "CONSUMER_SECRET",
                "TOKEN_SECRET"
        ).joinToString("&")

        authentication["oauth_signature"] = computeSignature(signatureUrl, signatureKey)

        val authenticationHeaderValue = authentication
                .toList()
                .joinToString { "${it.first}=\"${URLEncoder.encode(it.second, charset.displayName())}\"" }

        headers.contentType = MediaType.APPLICATION_JSON
        headers.add("Authorization", "OAuth $authenticationHeaderValue")
    }

    private fun computeSignature(data: String, key: String): String {
        val mac = Mac.getInstance(algorithm)
        mac.init(SecretKeySpec(key.toByteArray(charset), algorithm))
        return Base64.encodeBytes(mac.doFinal(data.toByteArray(charset)))
    }
}

What did I do wrong?

Matthew Layton
  • 39,871
  • 52
  • 185
  • 313

1 Answers1

1

There's an example of a working oAuth connection in Node at Netsuite OAuth Not Working

This line:

headers.Authorization += ',realm="' + config.accountId + '"';

appears to be what you are missing.

realm should not be part of the hash sent to compute signature.

bknights
  • 14,408
  • 2
  • 18
  • 31
  • 1
    Isn't `accountId` in this case, just what I've got for `realm` in my authentication map? I mean ultimately it's probably the same value, with a different property name, right? – Matthew Layton Feb 08 '19 at 22:19
  • 1
    should not be part of the signature. It's added after the oAuth hash is calculated. – bknights Feb 11 '19 at 16:47
  • Did you ever get this working @MatthewLayton? I'm currently facing the same issue! – Aimee Jones Feb 04 '20 at 13:25
  • Actually, I've figured it out and posted an answer on another question: https://stackoverflow.com/a/60059112/1728788 – Aimee Jones Feb 04 '20 at 14:06