Section 4.6 of RFC 5849, which defines OAuth 1, states that the consumer secret was never intended for use by desktop consumers, despite Twitter's use thereof in practice. As Nelson Elhage pointed out in "Dear Twitter", Twitter can and does terminate consumer keys of desktop clients, provided that the client isn't too big to fail. But there are two workarounds to allow use of OAuth 1 in a desktop or mobile application.
One way is to proxy the entire Twitter protocol through a server that you operate. This way, the consumer secret stays on your server. This is the workaround recommended by Dick Hardt, editor of the OAuth 1 spec. This workaround does not address the cost of operating this server.
The other way, as suggested in a post by Raffi Krikorian to the Twitter development talk Google group and a post by Chris Steipp to a Wikipedia mailing list, is to "have each user register their copy of your desktop application as its own consumer." Then the user would copy and paste the newly registered consumer key and consumer secret into your application. The manual for your application would then need to include detailed instructions on how to register a new application on Twitter's developer site. This official limitation has a few practical problems:
- Your client will face a usability disadvantage compared to well-known proprietary clients.
- The form to create a new app doesn't appear to offer a way to pre-populate the required fields. This means you will have to update the registration walkthrough in your manual whenever Twitter changes the procedure for registering an app.
- The developer agreement requires users to be of legal age to enter a binding contract. This means a user of your application aged 13 to 17 must have a parent accept the agreement on the user's behalf.
- Twitter's Developer Policy prohibits mass-registering applications and "name squatting", which it defines as "submitting multiple applications with the same function under different names." I am unaware of any precedent as to whether Twitter has treated unrelated users who have registered separate copies of one application as "name squatters".
Eh, answering my own question... I followed up a bit more on UMA, and it seems to be indeed some kind of a possible solution:
UMA seems to be a semi-official (or at least the only official-looking one I could find) extension to OAuth 2.0, adding support for "fine grained", M:N sharing of resources. In simple words, it allows a scenario such as:
"Alice shares a folder of cat photos with Bob."
The UMA spec itself is, um... somewhat of a bucketload of wordy formalese, as specs of this world like to be; but if you squeeze it to get to the juice, it suddenly starts to show as actually quite approachable, in my opinion. The core underlying "trick" I'd say is in an idea that:
"It should be AS's responsibility (to guard the access & manage individual permissions), but it would work on opaque resource pointers provided by RS (thus not needing to know about semantics of particular resources)."
Expanding a bit more on the idea, a "high level" architecture sketch of a possible implementation could be like below:
- Authorization Server must store one extra persistent table, "resource_sets", where each row represents "an opaque pointer to some concrete resource(s) in RS". [For example, a row could represent Alice's folder named: "Rly funny CATS!!!1!1"] The columns would need to be more or less:
id
— unique row ID in the AS
owner
— Resource Owner of the resources [e.g. "alice"
]
rs_id
— ID provided by Resource Server (the "opaque pointer")
name
— human-friendly name, also provided by RS [e.g. "Rly funny CATS!!!1!1"
]
max_scopes
— also provided by RS [e.g. "view"
, or "view add delete"
]
- a list of
(user, scopes)
pairs, dynamically managed by Resource Owner via some UI on AS. (This could be kept in a separate table if needed, implementation detail.) [e.g. ("bob", "view")
]
- AS must also expose a REST API, through which Resource Server can create, edit, and delete resource_sets entries (more details in the UMA spec),
- and a UI, through which RO can add/remove users & permissions, i.e.
(user, scopes)
pairs, to owned resource_sets (or at least some REST endpoints, so that implementer could build UI on those).
- Resource Server must keep a mapping of: resource → rs_id;
- when some Client requests a resource in RS, the RS must find the rs_id, and ask AS what are allowed scopes for this rs_id, through some elaborate dance using Access Tokens etc.
For full details, see obviously the full spec:
User-Managed Access (UMA) Profile of OAuth 2.0 [html]
EDIT: The 2.0 version of UMA spec in HTML format seems to be here, IIUC:
User-Managed Access (UMA) 2.0 Grant for OAuth 2.0 Authorization [html]
but I haven't looked into it yet, to confirm if that's indeed related.
Best Answer
Your native app client should use one client ID. In fact for most services you will get only one ID for your registered client (app).
It seems like you have some problems with the terminology in OAuth 2.0 (client, resource owner, resource, authorization), so maybe read a tutorial e.g. this short one to get a grasp for it.