indieweb / indieauth

IndieAuth.net website code and IndieAuth Specification
52 stars 7 forks source link

Standard mechanism for requesting a ticket auth ticket grant? #87

Open fluffy-critter opened 3 years ago

fluffy-critter commented 3 years ago

As an extension to Ticket Auth, it might be nice to optionally support the ability for someone to request a ticket to be sent to them by the provider's token endpoint. For example, if user https://alice.example.com/ wants a ticket from https://bob.example.com/, then Alice could make a POST request to https://bob.example.com/tokens with parameters:

grant_type=ticket_request&subject=https://alice.example.com/

at which point Bob's token endpoint could (if supported) perform a ticket_endpoint discovery on Alice's profile page and then initiate the rest of the TicketAuth flow.

Alternately, this could signal Bob that there is a pending ticket request to send to Alice, and Bob can opt to continue the rest of the flow.

In effect, this would be an optional, standard "follow request" procedure, of which many developers are already baking something similar into their grant_type=ticket flows on their token endpoints for testing purposes.

Zegnat commented 3 years ago

For the record, I currently implement the following:

POST /tokens HTTP/1.1

action=ticket&me=https://alice.example.com/

I think it might be wrong to use grant_type. Having a hard time citing a specific section in the OAuth standard, but my intuitive sense of the flow is that every request to a token endpoint that includes a grant should be exchanged for a token. A request for a ticket is not like that, as its result is not a token. Instead it starts the flow that will send a grant (a ticket) to you.

It feels much closer to what response_type does. A response_type=code expects a code grant to be provided through a redirect back to the client. Maybe for the ticket, a response_type=ticket makes sense? That is, if we must stay within already known OAuth parameter names.

IndieAuth uses action for revocation, which is why I decided to use that. The request for a ticket felt enough like a wholy separate function from the OAuth flow that I did not feel a need to try and fit it in there.

I do think it makes a lot more sense to request for a specific subject than a specific me like I did. And will definitely be upgrading my implementation to use that parameter instead.

fluffy-critter commented 3 years ago

Ah, yeah, those verbs make a lot more sense. I like action=ticket&subject=https://example.com

sknebel commented 3 years ago

Shouldn't the request include the resource too?

fluffy-critter commented 3 years ago

Ah, good catch.

dshanske commented 2 years ago

What should be the possible responses to this? Should it just always respond identically, and if you don't get a ticket, it means the endpoint doesn't want to give you one?

fluffy-critter commented 2 years ago

I think that could just be an implementation detail, up to the implementer to decide how much information to give on the ticket grant itself. 202 Accepted is probably the best choice for all responses though; it's accepted the request for a ticket grant, even if that doesn't necessarily mean that a ticket grant will ever be sent.

But I'd also think it'd be acceptable for an implementation to give a 4xx with an appropriate error message, for example a 429 for the usual "retry later," or a 403 if they've been outright banned from requesting future tickets or the like.

dshanske commented 2 years ago

Still worth discussing.

Zegnat commented 2 years ago

I agree with @fluffy-critter that the response should be whatever is a valid HTTP response as decided by the server. If it must standardise on something, I would propose lifting a lot of what the Webmention spec has and saving us the time writing something new.

The cases are similar in that in both cases a party sends a POST request to an endpoint they discovered. Webmention returns a 201 if things are handled synchronously and 202 if asynchronously. Which could be copied here by responding with a 201 if the endpoint knows a token has succesfully been sent and a 202 if it is being handled in the background. Webmention also documents using only 400 and 500 for user request errors and server errors respectively. Which is about as much as we would expect here too, unless features lie the subcodes of 4xx become relevant.

dshanske commented 2 years ago

I have been looking at this again to make a notation on the spec of this as a proposal. There are a few questions.

  1. Should this really be to the token endpoint, not the ticket endpoint? We have the ticket endpoint, maybe it should be the one to receive requests.
  2. What about ticket/token endpoints that have multiple users or multiple resources? We should specify resource as a mandatory parameter here. You should have to say what you want access to. There is the right to send tickets with a different resource if you want to.
  3. Should it be the me parameter or the subject parameter? If you follow the spec, the response to this is to send parameters resource and subject to a ticket endpoint. But in response to me?
dshanske commented 2 years ago

Thinking again about the ticket endpoint vs the token endpoint. The token endpoint is the one granting a token. The job of the ticket endpoint is to receive and redeem tickets. Technically speaking, you don't have to have a ticket endpoint to issue tickets, and you don't need a token endpoint to redeem tickets. So the initial proposal is probably the right one.

fluffy-critter commented 2 years ago

A thing which has come up recently that needs consideration for the actual draft spec, whenever this occurs: Since the actual request/verification flow is precisely backwards from IndieAuth, the usual mechanism for URL redirection no longer applies. This became an issue recently when someone requested a ticket from my token endpoint but used the http:// version of their identity URL instead of https://, which led to them getting a token for http://, which was the wrong identity for authentication on my site.

For now what I've decided to do in my implementation is if the request comes from a URL which has a rel="canonical" that points to a different URL, to retrieve that other URL and use that (and its ticket endpoint) as the granted identity. I believe that this is the best approach given the design of TicketAuth in general, so any spec that talks about the request flow should also recommend (i.e. RFC SHOULD) this mechanism or something similar.

Relevant discussion:

Publ's implementation of rel="canonical" for TicketAuth request grants: https://github.com/PlaidWeb/Publ/pull/487 (particularly tokens.get_ticket_endpoint and its related not-quite-a-unit test