Remotely Claim or Transfer Device Ownership to a Customer

@jeiden & @brycekahle

I’ve posted this question on a few other threads, but moved it here because I think it deserves it’s own topic.

We’re migrating to Particle’s recommended two-legged authentication. Until now, we’ve been managing our own user accounts/authentication and communicating with Particle exclusively through our server. i.e.

our users -> our mobile/web app -> our server -> Particle

Our server is currently using a single “never-expiring-token” to communicate with Particle, and make all device calls. We have DB tables associating our users with the devices they own, and “scope” control for a given user in that way. With this configuration, all of our devices (most assigned to our Particle product id, some generic photons) are owned/claimed by a single user on our team’s Particle account. We have not yet created Particle customers.

As I migrate to two-legged auth, I will create a Particle customer + scoped token + claim code via our app when our users create an account with us and bring our device online for the first time. But I need to circle back to the devices already in the field. I want to write a script to retroactively create Particle customers for all the users in my db, then associate their devices and use properly scoped tokens. How can I do that? I tried unclaiming a device, then reclaiming using a customer scoped token… but no success. The device seems to have moved beyond my visibility/control entirely.

Is there a way to remotely transfer ownership/claim of a device to a customer? Asking all my users to go through the SoftAP process again (i.e. bringing the device back online with a new claim code) would be really inconvenient.

1 Like

Hey @mebrunet,

Let me chat with @bryce and circle back with you.

Thanks,

Jeff

1 Like

OK @mebrunet,

I talked with Bryce. Basically what it comes down to is that you do have a way to unclaim each one of the devices from the user account relatively easily (you can do this through the dashboard), but where you are stuck is the reclaiming as a customer.

Right now, the system is limited to only claim customers during the claim code flow. What we are discussing is expanding the POST /v1/devices endpoint (docs) to work for both users and customers. That is, if you hit that endpoint with a customer access token, the device would be claimed to a customer account. If instead you hit that endpoint with a user account, it would be claimed to a user. Or, some variation of what I’m saying here.

We need to discuss this internally today and think about the security implications of this. I wouldn’t count on a solution being ready immediately.

If you are desperate for an immediate solution, we can consider the option of having you send us a list of Device IDs, and we’d manually shift account ownership for you. How urgent is your timeframe?

Thanks,

Jeff

1 Like

Yes, exactly. I can unclaim, but not reclaim as a Customer.

Posting to /devices sounds like a reasonable approach. It’s intuitive, and was the first thing I tried. (Haha - that device is now lost in the ether. Somehow claimed, but uncontrollable by any token I can generate.) However, I don’t like how that flow requires the device to be temporarily “unclaimed”. A transfer would seem more appropriate.

Here is my situation, that you may want to keep in mind as you make these decisions.

We sell our device (a WiFi control system for motorized window coverings) to manufacturers of window coverings, we help them re-brand it and embed it into their products. They in turn sell through their dealers to end users.

The device itself needs to run different firmware versions (i.e. change between Particle products) depending on the manufacturer we sell to, and how it is embedded into their product. This is because the exact role it plays, and what peripherals it needs to interact with will change depending on the manufacturer.

Moreover, both the manufacturers and dealers, want some level of access to the device, because servicing the end user is as much their job as it is ours. While we control all of this now, we will eventually want to let them do a certain amount of remote configuration, monitoring, and troubleshooting.

So really, I think the proposed two-legged authentication may be too rigid for our needs. In the current model.

  • Can a device be owned by more than one Customer?
  • If owned by a Customer, can it still be controlled by a User on the global account? (I assume yes on this one.)
  • Once owed by a Customer, can it change to become a different Product?

Because what I want is to be able to do is:

  1. Claim all devices to our central account.
  2. Assign / re-assign devices to a product remotely via the API. (And flash a small subset of individual ones with experimental firmware.)
  3. Create Users and Groups with different privileges on different devices (possibly overlapping), following a more general ACL model. i.e. I create Users and Groups, give them permissions on the devices they need access to, then generate scoped tokens for them.

With regards to the urgency, we’re designing backend upgrades now. We’ve got 25 or so devices online and in use, 80 or so more shipped, and there will be about 1000 in our client’s hands by the end of May. So it’s a problem that get’s bigger the longer we wait.

All that being said, with the current structure of two-legged auth, we may just need to continue making all the requests through our backend. Or whatever else you’d recommend given our use case.

No. We have ideas around access sharing, but ultimately still having a single account as the owner.

Yes.

No. When you import devices, we filter out devices which are different products already owned by customers. Right now, you would need to unclaim it first. I will discuss this with the team to see if there are any changes we can make here.

Yes, there is currently a bug around using that endpoint as a customer. If you PM me the device id I can fix it for you.

Okay -

It sounds like the flexibility we want might not be there yet… However, I’d really like to get my servers out of the middle wherever possible.

The minimum I need to start using the Customer / scoped-token approach would be the ability to remotely claim / unclaim a device to a Customer via the API. Once I have that, I can properly migrate existing devices. I’ll also know that in the worst case, if I push broken code I can clean it up remotely.

As for switching between Products and multiple Customer ownership of a device, I can probably find reasonable short term work arounds as you guys figure out what you’re going to do.

What’s the ETA on being able to claim using the POST /devices approach?

Will PM you that device ID.

Sometime this week.

1 Like

@bryce - where you guys at with this?

@mebrunet Sorry for not circling back to you! You should be able to claim as a customer using the POST /v1/devices endpoint now.

1 Like

Great I’ll experiment this afternoon.

Okay - sort of working. This is what I did.

1- isolated a device on our product list, let’s pretend it has device id - 12341234
2- hit DELETE /v1/devices/12341234 with our master (Particle Build) token.
3- created a customer, user@email.com - no password using an OAuth Client of type installed.
4- generated a never-expiring token for that customer at POST /oauth/token.
5- Claimed the device with POST /v1/devices {id:12341234} using the new customer token.

Now I can see the device at GET /v1/devices and read its variables at GET /v1/devices/12341234/some_variable but only using the customer token. i.e. my master token and CLI no longer work.

What’s weirder, I can see the customer and their device in the Customers tab of the dashboard. But I cannot see the device in the Devices tab.

What’s going on? I thought all Users on my account would maintain control over the device.

EDIT:

Correction, I can see the device on the Product dashboard under Devices, and what it publishes under Logs, however it remains seemingly invisible to the Developer dashboard and CLI… it looks like it’s hidden from the /devices endpoint using any token other than the Customer’s.

EDIT 2:

@bryce - You said YES I should be able to control Customer claimed devices through a User on my global account, but I don’t seem to be able to create a token that can do so. (This appears to be true whether I claim the device to a Customer via the devices endpoint, or using the claim code method). It would be key to have some kind of a master token to manage all Customer owned devices.

Also the Customer owned devices do not seem to trigger their webhooks anymore.

Finally, it seems important to have a Customer claiming/unclaiming method that doesn’t ever unclaim the device from the master account.

The key missing step here is you need to import the device into the dashboard. This will set the product_id on the device, which will fix all the issues you are running into.

Both devices I tried this with were imported as products. One prior to claiming as a customer, the second after. This is why I can see them on the Product dashboard. Could it be something else?

You are probably using the user/customer endpoints instead of the org endpoints:

Try /v1/orgs/:orgSlug/devices/:deviceId as a base instead of /v1/devices/:deviceId for all the individual device functions. For listing, you currently must do it under a product at /v1/orgs/:orgSlug/products/:productSlug/devices.

1 Like

Ahh… that’s a sneaky endpoint I didn’t try. I had tried both:

  1. /v1/devices/:deviceId -> getting a 403 with a User token, and a 200 with the Customer’s token
    and
  2. /v1/orgs/:orgSlug/products/:productSlug/devices/:deviceId -> getting a 404 with both tokens,

but not
3) /v1/orgs/:orgSlug/devices/:deviceId where I now see that I get a 200 with the User’s token, but a 404 with the Customer’s…

So there’s no single endpoint where I can use both a Customer scoped AND global or User’s token?

Also, how do I get Webhooks working on devices owned/claimed by a Customer? I assume they aren’t working now because while events published by Products that are still owned by a User of the Org appear both on:

  1. /v1/devices/events
    and
  2. /v1/orgs/:orgSlug/products/:productSlug/events

once they are owned by a Customer they only show up on 5.

Sorry to revive an only thread but seems the most relevant. I’m trying to remotely claim a customer’s photon that is already connected to the internet that shows up with no owner in the console dashboard.

  1. I created a customer with the client_id and client secret
    curl https://api.particle.io/v1/products/:productSlug/customers -d client_id="client-id" -d client_secret="secret" -d email="jane@example.com " -d no_password=true

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

  3. Tried to remotely claim the device with
    v1/products/:productSlug/devices?access_token=customer_access_token&id=deviceID
    as well as
    /v1/devices?access_token=customer_access_token&id=deviceID

for the first one i get:
{ "ok": false, "error": "Organization not found for user's role." }
and for the second one I got:
{ "ok": false, "errors": [ "data.deviceID is empty" ] }

I’m sure it is something simple I’m missing.

I ran into the same problem as UMBrew and thought I would include the solution here for anyone else banging their head against this. Through trial and error, I finally got it to work by (1) targeting a non-product endpoint and (2) including the data in the body rather than the query string. For (1), the documentation is currently not very clear on this. Most calls seem to have user-level and product-level endpoint but in this case not. For (2), this is required for a POST, including data in the query string only works for GET. With all that said, this is what worked for me:

curl -X POST https://api.particle.io/v1/devices -d id=deviceID -d access_token=1234

where the access token is of course customer-scoped.

1 Like