# Authorization API not working

**URL:** <https://discuss.dwolla.com/t/authorization-api-not-working/6234>\
**Category:** API Support\
**Created:** [September 27, 2020, 9:35pm UTC](https://discuss.dwolla.com/t/authorization-api-not-working/6234 "2020-09-27T21:35:10Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![burte123](https://sea2.discourse-cdn.com/dwolla/user_avatar/discuss.dwolla.com/burte123/32/2662_2.png) [@burte123](https://discuss.dwolla.com/u/burte123)\
**Post date:** [September 27, 2020, 9:35pm UTC](https://discuss.dwolla.com/t/authorization-api-not-working/6234/1 "2020-09-27T21:35:10Z")

</div>

I am developing an iOS app using Swift code and want to integrate the Plaid/Dwolla ACH processing. I have a common function that essentially creates the raw cURL commands for doing this. Of course for each endpoint the parameters of the cURL request change appropriately. This function works fine for all the Plaid endpoints (link tokens, access tokens, processor tokens, etc.). It also works with the Dwolla endpoints that I have tried with one big exception, Authorization.

If I click on the “Create Token” button when I log in to the dashboard, I get the temporary access token, which I can then use successfully for endpoints like “GET Root” (GET …api-sandbox.dwolla.com/), “POST Create Customer” (POST …api-sandbox.dwolla.com/ customers), and “GET Get Customers” (GET …api-sandbox.dwolla.com/ customers). These functions all worked fine using Authorization: Bearer access token.

However the Authorization function “POST [https://api-sandbox.dwolla.com/token”](https://api-sandbox.dwolla.com/token%E2%80%9D) did not work for me. I use the two parameters from my dashboard concatenated together for Authorization: Basic. The body was “grant\_type=client\_credentials”. All other API requests use a key:value pair for the body, so I’m not sure why you use a statement with an equal sign. So I also tried “grant\_type”: “client\_credentials” in the body. Both gave the same error:

[“code”: InvalidCredentials, “message”: Missing or invalid Authorization header.]

As I say above the Authorization: Bearer header works so I don’t know why the Authorization: Basic doesn’t work. I use the same two parameters as is used with the dashboard “Create Token” button.

Here is a printout of what I am sending (with secret edited). I had to remove https: from the links since it would not let me post with active links, but all the links are https://. The 33 bytes of the body translates to [“grant\_type=client\_credentials”].

▿://api-sandbox.dwolla.com/token  
▿ url : Optional  
▿ some ://api-sandbox.dwolla.com/token  
- \_url : ://api-sandbox.dwolla.com/token

- cachePolicy : 0
- timeoutInterval : 60.0
- mainDocumentURL : nil
- networkServiceType : \_\_C.NSURLRequestNetworkServiceType
- allowsCellularAccess : true  
▿ httpMethod : Optional
  - some : “POST”  
▿ allHTTPHeaderFields : Optional\<Dictionary\<String, String\>\>  
▿ some : 2 elements  
▿ 0 : 2 elements
    - key : “Authorization”
    - value : "Basic 37r8iVcRCxhOmo6YHRtfvPw5KD5hpXks5rRS5DZuEW2sx3QFDPnSbZKfmTzkAbjyTPP…”  
▿ 1 : 2 elements
    - key : “Content-Type”
    - value : “application/x-www-form-urlencoded”  
▿ httpBody : Optional  
▿ some : 33 bytes
    - count : 33  
▿ pointer : 0x00007fc34a89aa00
      - pointerValue : 140476745886208  
▿ bytes : 33 elements
      - 0 : 91
      - 1 : 34
      - 2 : 103
      - 3 : 114
      - 4 : 97
      - 5 : 110
      - 6 : 116
      - 7 : 95
      - 8 : 116
      - 9 : 121
      - 10 : 112
      - 11 : 101
      - 12 : 61
      - 13 : 99
      - 14 : 108
      - 15 : 105
      - 16 : 101
      - 17 : 110
      - 18 : 116
      - 19 : 95
      - 20 : 99
      - 21 : 114
      - 22 : 101
      - 23 : 100
      - 24 : 101
      - 25 : 110
      - 26 : 116
      - 27 : 105
      - 28 : 97
      - 29 : 108
      - 30 : 115
      - 31 : 34
      - 32 : 93

- httpBodyStream : nil
- httpShouldHandleCookies : true
- httpShouldUsePipelining : false

Here is the complete response from the endpoint:

▿ Optional

- some : \<NSHTTPURLResponse: 0x6000000724e0\> { URL://api-sandbox.dwolla.com/token } { Status Code: 401, Headers {  
“Access-Control-Allow-Origin” = (  
“\*”  
);  
“Content-Length” = (  
82  
);  
“Content-Type” = (  
“application/vnd.dwolla.v1.hal+json; profile=”://nocarrier.co.uk/profiles/vnd.error/""  
);  
Date = (  
“Sun, 27 Sep 2020 21:16:54 GMT”  
);  
Server = (  
cloudflare  
);  
“Set-Cookie” = (  
“\_\_cf\_bm=cce82e97ca661ec448cbebb3eed4ca4db9c5e875-1601241414-1800-Af5ZfJLsbPtR3Yfkw9IoG+6TWlaM5xs8u9rglrZ6X6FeQcN28YSGvLkbFtcJ9M7ZcDEKjxvhmWQ8CG7Tv8bKX6Y=; path=/; expires=Sun, 27-Sep-20 21:46:54 GMT; [domain=.dwolla.com](http://domain=.dwolla.com); HttpOnly; Secure; SameSite=None”  
);  
“cf-cache-status” = (  
DYNAMIC  
);  
“cf-ray” = (  
“5d983f981820f045-EWR”  
);  
“cf-request-id” = (  
05730613110000f045dc90d200000001  
);  
“expect-ct” = (  
“max-age=604800, report-uri=”://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct""  
);  
“x-request-id” = (  
“46508a67-ee16-4e2a-bfce-3c27dee3515e”  
);  
} }

---

<div class="post-metadata">

**Author:** ![shreya](https://sea2.discourse-cdn.com/dwolla/user_avatar/discuss.dwolla.com/shreya/32/2154_2.png) [@shreya](https://discuss.dwolla.com/u/shreya)\
**Post date:** [September 28, 2020, 2:57pm UTC](https://discuss.dwolla.com/t/authorization-api-not-working/6234/2 "2020-09-28T14:57:10Z")

</div>

Hi Burt – thanks for posting a detailed explanation and also the code for us to reference. This is very helpful! 🙂

> [@burte123](#):
>
> I use the two parameters from my dashboard concatenated together for Authorization: Basic.

^ This may be where the issue lies.

The [Authorization](https://docs.dwolla.com/#authorization) header expects a base64 encoded string of the client id:client secret. Would you be able to give that a try and see if it works? i.e. Concatenate client\_id and client\_secret separated with a `:`, and then base64 encode it.

> Authorization: Basic Base64(client\_id:client\_secret)

Let me know if that works or not!

---

<div class="post-metadata">

**Author:** ![burte123](https://sea2.discourse-cdn.com/dwolla/user_avatar/discuss.dwolla.com/burte123/32/2662_2.png) [@burte123](https://discuss.dwolla.com/u/burte123)\
**Post date:** [September 28, 2020, 5:07pm UTC](https://discuss.dwolla.com/t/authorization-api-not-working/6234/3 "2020-09-28T17:07:37Z")

</div>

I was dumb ignoring that. The encoded string ends with an = sign which is what all the examples show. So I think I am sending the correct string now.  
However, I just tried that but I get the same error.

---

<div class="post-metadata">

**Author:** ![burte123](https://sea2.discourse-cdn.com/dwolla/user_avatar/discuss.dwolla.com/burte123/32/2662_2.png) [@burte123](https://discuss.dwolla.com/u/burte123)\
**Post date:** [September 29, 2020, 4:46pm UTC](https://discuss.dwolla.com/t/authorization-api-not-working/6234/4 "2020-09-29T16:46:21Z")

</div>

Since now that I am fairly confident that I am sending the correct encoded string, the only thing left is the body of the request: grant\_type=client\_credentials. It seems like your /token endpoint does not like the way I am sending it. As an experiment I removed the body and I get the same error, so it does appear as though it is ignoring the body I send as:  
[“grant\_type=client\_credentials”].

This brings up an interesting point. Why is this data in the body even required. It is the same for all users so it provides no additional information, it really makes no sense to have to send anything in the body. The base64 encoded string contains everything needed, why send anything in the body if everyone sends the same thing. Second point, if you are going to require this, why was it done as a phrase x=y, all other API requests use a [key:data] pair in the body as I have mentioned in previous posts. Who came up with this and why was it done in the non-standard way. How did it get past QA.

So I have a request. Can you modify the /token endpoint such that it simply ignores the body. Or if you really want to require data then in addition to the current phrase, add an option to accept it as:  
[“grant\_type”: “client\_credentials”], the same as all your other API requests.

Can you talk to your engineering group about this.

---

<div class="post-metadata">

**Author:** ![shreya](https://sea2.discourse-cdn.com/dwolla/user_avatar/discuss.dwolla.com/shreya/32/2154_2.png) [@shreya](https://discuss.dwolla.com/u/shreya)\
**Post date:** [September 29, 2020, 6:37pm UTC](https://discuss.dwolla.com/t/authorization-api-not-working/6234/5 "2020-09-29T18:37:44Z")

</div>

Hmm…would you be able to give the following cURL command a try?

```auto
CLIENT_ID=CLIENTID
CLIENT_SECRET=CLIENTSECRET
AUTH=$(echo -ne "$CLIENT_ID:$CLIENT_SECRET" | base64)
echo $AUTH
curl \
  --header "Content-Type: application/x-www-form-urlencoded" \
  --header "Authorization: Basic $AUTH" \
  --request POST \
  --data 'grant_type=client_credentials' \
  https://api.dwolla.com/token

```

---

<div class="post-metadata">

**Author:** ![burte123](https://sea2.discourse-cdn.com/dwolla/user_avatar/discuss.dwolla.com/burte123/32/2662_2.png) [@burte123](https://discuss.dwolla.com/u/burte123)\
**Post date:** [September 29, 2020, 6:57pm UTC](https://discuss.dwolla.com/t/authorization-api-not-working/6234/6 "2020-09-29T18:57:28Z")

</div>

Remember I am doing this from inside an iOS app, not from a terminal or browser. If you mean CLIENTID is my client\_id and CLIENTSECRET is my client\_secret, well that is what I am already doing. I concatenate them, separate with : and convert to base64, and I send this data after Basic. And I send the data in the body as previously mentioned.

So I’m not sure what you are asking. This is what I am doing. It simply does not seem to recognize the way I send the data in the body.

---

<div class="post-metadata">

**Author:** ![shreya](https://sea2.discourse-cdn.com/dwolla/user_avatar/discuss.dwolla.com/shreya/32/2154_2.png) [@shreya](https://discuss.dwolla.com/u/shreya)\
**Post date:** [September 29, 2020, 7:01pm UTC](https://discuss.dwolla.com/t/authorization-api-not-working/6234/7 "2020-09-29T19:01:28Z")

</div>

Ah gotcha. My bad. Perhaps this might help to try -

```auto
$id = "YOUR DWOLLA CLIENT ID HERE";
$secret = "YOUR DWOLLA CLIENT SECRET HERE"

$curl = curl_init();
//config request
curl_setopt($curl, CURLOPT_URL, DWOLLA_API_ENDPOINT."/token");
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS,
            "client_id=$id&client_secret=$secret&grant_type=client_credentials");
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

// receive server response ...
$server_output = curl_exec ($curl);
curl_close ($curl);

//pull access token

```

---

<div class="post-metadata">

**Author:** ![burte123](https://sea2.discourse-cdn.com/dwolla/user_avatar/discuss.dwolla.com/burte123/32/2662_2.png) [@burte123](https://discuss.dwolla.com/u/burte123)\
**Post date:** [September 29, 2020, 7:36pm UTC](https://discuss.dwolla.com/t/authorization-api-not-working/6234/8 "2020-09-29T19:36:44Z")

</div>

I don’t want to be difficult, but no, that does not help. What you are showing doesn’t even do the base64 encoding, or include the Authorization Basic header. I can see that the rest includes the information, but how can that possibly work.

If it helps I can post a code snippet of how I send the cURL request, but I don’t think it would prove much.

Again, I know you are trying to help, but can one of your developers get involved.  
Thanks.

---

<div class="post-metadata">

**Author:** ![stephen](https://sea2.discourse-cdn.com/dwolla/user_avatar/discuss.dwolla.com/stephen/32/2936_2.png) [@stephen](https://discuss.dwolla.com/u/stephen)\
**Post date:** [September 30, 2020, 6:24pm UTC](https://discuss.dwolla.com/t/authorization-api-not-working/6234/9 "2020-09-30T18:24:21Z")

</div>

Hey @burte123,

A code snippet could help us track down what’s going on, but the `key` and `secret` are only intended to be used on a secure server and not distributed with client applications.

Do you have a server environment somewhere? If so, we have some [SDKs](https://developers.dwolla.com/sdks-tools) that make it easier to get up and running depending on what language you’re using.

---

<div class="post-metadata">

**Author:** ![vinod](https://avatars.discourse-cdn.com/v4/letter/v/bbce88/32.png) [@vinod](https://discuss.dwolla.com/u/vinod)\
**Post date:** [September 30, 2020, 6:32pm UTC](https://discuss.dwolla.com/t/authorization-api-not-working/6234/10 "2020-09-30T18:32:55Z")

</div>

![image](https://global.discourse-cdn.com/dwolla/original/2X/4/493a17b10da9907f70bbca3670fc1178dcb1337a.png)

---

<div class="post-metadata">

**Author:** ![burte123](https://sea2.discourse-cdn.com/dwolla/user_avatar/discuss.dwolla.com/burte123/32/2662_2.png) [@burte123](https://discuss.dwolla.com/u/burte123)\
**Post date:** [September 30, 2020, 8:14pm UTC](https://discuss.dwolla.com/t/authorization-api-not-working/6234/11 "2020-09-30T20:14:35Z")

</div>

Thanks for responding. Please clarify the situation. I am using the Plaid+Dwolla integration embedded inside my iOS app. I store my client\_id and client\_secret as constants in the app. They are not stored in core data memory on the device. So they get compiled as part of the source code. Someone would have to reverse engineer the app and recreate the source code in order to see these constants. As far as I know no one has ever claimed to have been able to do this. So I think it is pretty secure. Are you saying Dwolla would not allow this and ultimately would not approve it for production?

In any case I also use Google Firestore in my app. That is certainly a secure server. I could store client\_id and client\_secret in my database and retrieve them whenever a user starts to initiate an ACH transfer. Of course, setting them as constants inside the app is much cleaner and simpler. So let me know what you think of all this.

As far as the actual problem here is a code snippet of how I compose and send the RAW protocol. I used the wrong terminology in previous posts as I am not really sending cURL commands, but simply sending RAW commands as shown in your API documentation. In full disclosure I did not write this function. I got it from Square. They publish it in their documentation for using Square with an iOS app. As I mentioned this function works for all Square, Plaid, and your (Dwolla) API endpoints, except Authorization.

```
    let url = URL(string: Utilities.Dwolla.SERVER_ROOT+"/token")!
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    let json = ["grant_type=client_credentials"]
    let httpBody = try? JSONSerialization.data(withJSONObject: json)
    request.addValue("Basic MzdyOGlWY1JDeGhPbW82WUhSdGZ2UHc1S0Q1aHBYa3M1clJTNURadUVXMnN4M1FGRFA6blNiWktmbVR6a0FianlUUFBDdlFmZjVaSlc5TDJ1bHd…=", forHTTPHeaderField: "Authorization")
    request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    request.httpBody = httpBody
    
    URLSession.shared.dataTask(with: request) { data, response, error in}

```

It seems the issue is that your endpoint doesn’t like the way I send the body. I gave me feelings on this in previous posts so I won’t repeat them. What is your thinking on my requests. Or do you have code which I can use instead of the above which would work with this endpoint.  
Thanks.

---

<div class="post-metadata">

**Author:** ![stephen](https://sea2.discourse-cdn.com/dwolla/user_avatar/discuss.dwolla.com/stephen/32/2936_2.png) [@stephen](https://discuss.dwolla.com/u/stephen)\
**Post date:** [October 1, 2020, 3:43pm UTC](https://discuss.dwolla.com/t/authorization-api-not-working/6234/12 "2020-10-01T15:43:48Z")

</div>

> [@burte123](#):
>
> Are you saying Dwolla would not allow this and ultimately would not approve it for production?

Yeah, unfortunately. We have security requirements around where API credentials are stored since they can be used to access bank accounts, PII, etc. of yours and your users.

For this reason, your API credentials need to be stored on a secure server and cannot be distributed with your app to end-user devices.

* * *

> [@burte123](#):
>
> This brings up an interesting point. Why is this data in the body even required. It is the same for all users so it provides no additional information, it really makes no sense to have to send anything in the body. The base64 encoded string contains everything needed, why send anything in the body if everyone sends the same thing. Second point, if you are going to require this, why was it done as a phrase x=y, all other API requests use a [key:data] pair in the body as I have mentioned in previous posts. Who came up with this and why was it done in the non-standard way. How did it get past QA.

In this case we chose to implement [OAuth 2](https://tools.ietf.org/html/rfc6749), an industry standard auth framework. The [`grant_type=client_credentials`](https://tools.ietf.org/html/rfc6749#section-4.4) request body is specified as part of the OAuth spec, which is why it’s different from the rest of our API requests.

Our official SDKs abstract this away so you don’t have to worry about it. If we don’t have an SDK for the language you’re using, I would look to see if an OAuth 2 library exists for that language (e.g. [Ruby](https://github.com/oauth-xx/oauth2)), or try Googling OAuth 2 client\_credentials examples for you language.

* * *

> [@burte123](#):
>
> ```auto
> let url = URL(string: Utilities.Dwolla.SERVER_ROOT+"/token")!
> var request = URLRequest(url: url)
> request.httpMethod = "POST"
> let json = ["grant_type=client_credentials"]
> let httpBody = try? JSONSerialization.data(withJSONObject: json)
> request.addValue("Basic MzdyOGlWY1JDeGhPbW82WUhSdGZ2UHc1S0Q1aHBYa3M1clJTNURadUVXMnN4M1FGRFA6blNiWktmbVR6a0FianlUUFBDdlFmZjVaSlc5TDJ1bHd…=", forHTTPHeaderField: "Authorization")
> request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
> request.httpBody = httpBody
>     
> URLSession.shared.dataTask(with: request) { data, response, error in}
> 
> ```

The only thing that looks off to me is:

```swift
let httpBody = try? JSONSerialization.data(withJSONObject: json)

```

since the request body is expected to be `application/x-www-form-urlencoded` and not JSON encoded. It may work if you do:

```swift
let httpBody = "grant_type=client_credentials"

```

which is a `application/x-www-form-urlencoded` string.

* * *

I’m sure this isn’t what you wanted to hear regarding the distribution of credentials with your app not being allowed, but if you have any follow-up questions don’t hesitate to ask.

---

<div class="post-metadata">

**Author:** ![burte123](https://sea2.discourse-cdn.com/dwolla/user_avatar/discuss.dwolla.com/burte123/32/2662_2.png) [@burte123](https://discuss.dwolla.com/u/burte123)\
**Post date:** [October 1, 2020, 11:30pm UTC](https://discuss.dwolla.com/t/authorization-api-not-working/6234/13 "2020-10-01T23:30:09Z")

</div>

Success! I got it to work and return an access token. Your suggestion was on the right track but not quite. let httpBody = “x” doesn’t work because request.httpBody must be of type Data. It does not allow setting it to a String. And you can’t coerce the string to Data.

However, I did some searching as you suggested and found some source code in GitHub which allowed it to work. Here is the code (simplified from the original post).

```
    let httpBody = "grant_type=client_credentials".data(using: String.Encoding.utf8)
    request.httpBody = httpBody

```

To clarify the point about using a secure server for client\_id and client\_secret. I assume that it would be okay to use Google Firestore and I would store the base64(client\_id:client\_secret) in my database, not the individual elements.

---

<div class="post-metadata">

**Author:** ![stephen](https://sea2.discourse-cdn.com/dwolla/user_avatar/discuss.dwolla.com/stephen/32/2936_2.png) [@stephen](https://discuss.dwolla.com/u/stephen)\
**Post date:** [October 5, 2020, 9:15pm UTC](https://discuss.dwolla.com/t/authorization-api-not-working/6234/14 "2020-10-05T21:15:29Z")

</div>

> [@burte123](#):
>
> To clarify the point about using a secure server for client\_id and client\_secret. I assume that it would be okay to use Google Firestore and I would store the base64(client\_id:client\_secret) in my database, not the individual elements.

I believe as long as:

1. Credentials are stored securely (encrypted at rest)
  - Base64 encoding doesn’t provide encryption, so it would have to be something else like [Firestore server-side encryption](https://cloud.google.com/firestore/docs/server-side-encryption).

2. Credentials are not shared with end-user devices
  - Tokens created via the `/tokens` endpoint are only intended to be used by your server to interact with the Dwolla API because they grant permission to access the API on behalf of your entire account.

you should be good.

* * *

We do have some tokens such as [funding sources tokens](https://developers.dwolla.com/guides/dwolla-js/add-a-bank-account/create-token#step-2-generate-a-funding-sources-token) which can be created for a customer on your server and shared with a client (web browser, iOS app, etc.) in order to make requests directly to the Dwolla API from a device.

We’re looking to expand the number of endpoints that support this type of functionality, but as of now the majority of endpoints require requests be made from your server.

---

<div class="post-metadata">

**Author:** ![francopetra](https://sea2.discourse-cdn.com/dwolla/user_avatar/discuss.dwolla.com/francopetra/32/2695_2.png) [@francopetra](https://discuss.dwolla.com/u/francopetra)\
**Post date:** [October 22, 2020, 3:54pm UTC](https://discuss.dwolla.com/t/authorization-api-not-working/6234/15 "2020-10-22T15:54:42Z")

</div>

Hope this helps someone. I was in the same road and using `querystring` is what worked out for me:

```auto
    axios.post(
      `${functions.config().dwolla.sandbox}/token`,
      // note the use of querystring
      querystring.stringify({'grant_type':'client_credentials'}),
      { 
        headers: {
          'Content-Type':'application/x-www-form-urlencoded',     
          'Authorization': `Basic ${Buffer.from(`${key_sandbox}:${secret_sandbox}`).toString('base64')}`   
        }
      }).then((response: { data: string}) => {
        ...
      }).catch((error: string) => {
        ...
      });
    })

```
