Creating a New Customer (two legged auth) - Now Working

Continuing the discussion from OAuth client Error:

I am now attempting to create a new customer using both curl and http, I have issues with both.

1. CURL
I have successfully created an oAuth token, now trying to create a new customer:

Create oAuth Client

Use Access token in header

curl -X POST -H "Authorization: Bearer d91xxxxxxxxefd" -d name='Neighbour' -d type=installed -d organization=neighbour https://api.particle.io/v1/clients 

response

{
  "ok": true,
  "client": {
    "name": "Neighbour",
    "type": "installed",
    "id": "neighbour-xxxx",
    "secret": "9ddyyyyyyyyyd",
    "org_id": "55ccccccc5b"
}

All good here.

Create Customer

I use the Id and secret response from the oAuth client call to create a new customer. For this call I use the same Access Token in the header as in the previous call (that worked OK).

curl -X POST -H "Authorization: Bearer d91xxxxxxxxefd" -d email=user@mail.com -d no_password=true https://api.particle.io/v1/orgs/particle/customers -u neighbour-xxxx:9ddyyyyyyyyyd

{
  "ok": false,
  "error": "Organization not found."
}

This is using the exact same access token I used to create the oauth client in the first place - so why the organisation not found for this call but fine for the oauth client call?

For anyone viewing this thread, the example in the docs:
https://docs.particle.io/guide/how-to-build-a-product/authentication/#3-create-a-customer
does not mention how/where to use the oauth credentials. (curl -u client-id-1234:secret).

2. Http
I still set the access token in the Header
headers: {"Authorization" => "Bearer xxxxxxxx"}}
then call

    HTTParty.post("https://api.particle.io/v1/orgs/neighbour/customers",
                  { 
                    :body => [ { "email" => "user@mail.com", "no_password" => "true" } ].to_json,
                    :basic_auth => { :username => "neighbour-xxx", :password =>     
                          "9ddyyyyyyyyyd" },
                    :headers => { 'Content-Type' => 'application/json' }
                   })

Response:

parsed_response={"ok"=>false, "code"=>400, "error"=>"email was empty"}

Is this really a no email problem?

Is the API code available in github to view?

Can anyone spot issues with either or both of these attempts?

thank you.

2 Likes

Has anyone else managed to create a customer either via curl or an http post? Specifically using this method:
POST /v1/orgs/:orgSlug/customers

Using curl the response tells me the access token is not associated with the organisation. Http tells me I have not provided the email address (I will debug more to see if I have incorrectly set up the call)

OK, solved the curl issue - I didn't change the orgslug in the url (the example uses particle, need to change this for your org).

curl -X POST -H "Authorization: Bearer d91xxxxxxefd" -d email=user@mail1.com -d no_password=true https://api.particle.io/v1/orgs/neighbour/customers -u neighbour-xxxx:9ddxxxxxxx8d
{
"ok": true,
"status": "created"
}

However, the response is not returning a customer token, just the status.

@jeiden - would you be able to check this out please?

I am not too interested in the curl version, this was mainly to test the flow (but it is interesting that I do not get any tokens back). Could you confirm the values I am sending in the http call - the parameters passed are email and no_pasword?

I really need to get this working asap.

Thank you.

@Kevin sorry for the delay. Looks like you figured out you need to use your real organization’s slug in the request. Let me dig into why the token isn’t being returned

@Kevin, for now what you can do to continue to progress is use the “Generate a Scoped Access Token for customer” endpoint documented here: https://docs.particle.io/reference/api/#generate-a-customer-scoped-access-token.

You have the customer’s email now that it has been created, and now are able to hit POST /oauth/token to get a scoped access token for that customer.

curl -u my-org-client-1234:long-secret -d grant_type=client_credentials \
-d scope=customer=jane@example.com https://api.particle.io/v1/oauth/token

This endpoint is explained more thoroughly here: https://docs.particle.io/guide/how-to-build-a-product/authentication/#7-interact-with-customer-39-s-device

Can you let me know if this helps you?

Although I used curl in the example (that did not return the expected access token), I need to use e.g. HttpParty example above. I appreciate I cannot ask you to debug this, but can you comment on the response I am getting? It indicated I am not providing an email and clearly I am, unless the endpoint is expecting a different name?

Thanks for your assistance here - and I am hoping it will also help those who come upon this further down the line.

Can I also ask for comments on the general plan of attack to implement (two legged auth)

The first release of the service we are building is web based and using an iphone app just to setup the device wifi.

We have done the one time steps of getting a oauth client and stored on the server (using curl) (steps 1-2).
We use a web api call to create the customer (step 3)
Steps 4-6 are taken care of by the app - supply the customers email address (created at step 3) to get a claim code (step 4), set up wifi credentials (step 5) and finally map the user to the device (step 6).

Am I correct in thinking that if I get a user to create an account (and we create the shadow customer) on the website, the mobile app can be implemented to ask the customer to supply their email address and this is all that is required to link the device and setup the device.

@Kevin, I think I see what is going on here. In your initial cURL request:

curl -X POST -H "Authorization: Bearer d91xxxxxxefd" -d email=user@mail1.com -d no_password=true https://api.particle.io/v1/orgs/neighbour/customers -u neighbour-xxxx:9ddxxxxxxx8d

You are actually double authenticating. You are passing an authorization header with your token ("Authorization: Bearer d91xxxxxxefd") and your oAuth client credentials (-u neighbour-xxxx:9ddxxxxxxx8d).

In order for the endpoint to work correctly, you should only pass your client ID and secret, like this:

curl -X POST -u neighbour-xxxx:9ddxxxxxxx8d -d email=user@mail1.com -d no_password=true https://api.particle.io/v1/orgs/neighbour/customers 

This should return the customer with an access token. Can you give this a whirl? I realize that I need to update the guide in the docs for it to be less confusing. Does this work for you?

To answer your question, yes. The only requirement from the customer on our system is an email address. In two-legged auth, you will have your own database of customers (you may call them users) and manage usernames and passwords. As a result, we don't require you to send us a password for the customer to be saved in the Particle system.

Once the customer has been added to your organization, everything is good to go to claim a device for that customer. Here is documentation on organization-mode for the iOS SDK.

Yes, that has solved it. I thought the access token was required for all api calls, but obviously not in this case. Thanks for getting to the bottom of this one.

Awesome!!! That’s great news @Kevin. Keep us in the loop as you continue to build

So that is curl sorted. I have directly emailed the request/response for the httparty call that I need to use on the web app version. Hoping we can get this resolved and I will write up the solution and post for others.

@jeiden just to confirm, the test call:

HTTParty.post("https://api.particle.io/v1/orgs/neighbour/customers",
  { 
    :body => [ { "email" => "xxxxn@xxxxx.com", "no_password" => true } ].to_json,
    :basic_auth => { :username => "neighbour-xxxx", :password => "dc94xxxxxxxxxxx359a" },
    :headers => {"Content-Type" => "application/json"  }
   })
end

response:

"error"=>"email was empty"}

The correct version:

def test1
    HTTParty.post("https://api.particle.io/v1/orgs/your-org-goes-here/customers",
      { 
        :body =>  { "email" => "xxxx@xxxx.com", "no_password" => true }.to_json,
        :basic_auth => { :username => "your-org-xxxxx", :password => "dc9xxxxxxxxxx359a" },
        :headers => {"Content-Type" => "application/json"  }
       })
  end

Note: do not pass in the access token in the Header as you do with other calls.

This now works fine. Phew!

The Curl version, remember to passing in the organisations oauth credentials using -u:

curl -X POST -u your-org-xxxx:9ddxxxxxxx8d -d email=user@mail1.com -d no_password=true https://api.particle.io/v1/orgs/your-org-goes-here/customers
1 Like

Glad you got it working :smile:

I am still having trouble with this. First I use

"curl -X POST -H "Authorization: Bearer 1234" -d name=MyApp -d type=installed \ -d organization=my-org https://api.particle.io/v1/clients" 

and get the response I expect:

{
    "ok": true,
    "client": {
        "name": "MyApp",
        "type": "installed",
        "id": "myapp-2146",
        "secret": "615c620d647b6e1dab13bef1695c120b0293c342"
    }
}

Then I do:

curl -X POST -u myapp-2146:615c620d647b6e1dab13bef1695c120b0293c342 -d email=abu@agrabahmonkeys.com \
-d no_password=true https://api.particle.io/v1/orgs/my-org/customers         

but all I get in return is this:

{                                                                                                                                                                                                                       
  "ok": false,                                                                                                                                                                                                          
  "error": "Not Found",                                                                                                                                                                                                 
  "device_name": "hacker normal chicken zombie trochee"                                                                                                                                                                 
}

@bdi247 I ran your exact curl request in my terminal and got the following response:

{
  "ok": false,
  "error": "Organization not found."
}

I assume you are swapping out my-org with your actual organization slug. Once you add your correct organization slug this request should work just fine.

I am now getting this response:

{
“ok”: false,
“error”: “Organization not found for user’s role.”
}

Been a while, but back to creating customers. I have tried to create a scoped token for a customer for a 2 legged auth process:

curl -u my-client1-id:myclienttoken -d grant_type=client_credentials -d scope=customer=customer@email.com https://api.particle.io/oauth/token

give the following error:
{
“error”: “invalid_scope”,
“error_description”: “Requested customer scope doesn’t exist”

Also for parameter passing purposes how do I pass "scope=customer=customer@email.com" in a form? Is the query name “scope=customer” and then the value "customer@email.com"

thank you