IndieAuth Ticket Auth

From IndieWeb
(Redirected from TicketAuth)
Jump to navigation Jump to search

Ticket Auth is an extension to IndieAuth that enables a publisher to send authorization, known as a ticket, that can be redeemed for an access token. This allows both solicited and unsolicited invitations to fetch restricted resources.

Status
This specification is still in early development.
Latest Published Version
https://indieweb.org/IndieAuth_Ticket_Auth
Participate
chat
discussion on GitHub
Authors
Contributors: revision history

Introduction

Ticket Auth is an extension to IndieAuth that enables the granting of access to a protected resource (a.k.a. resource server, application, API, etc.). Ticket Auth differs from other proposed extensions in that the extension does not require the client accessing the protected resource to expressly request access, but is instead offered it.

Summary

  • Alice has choosen to share private things with Bob.
  • Bob advertises a ticket endpoint on his website.
  • Alice sends a ticket to Bob's ticket endpoint, which he can redeem for a token to access Alice's private things.
  • Bob's ticket endpoint receives a ticket, which he exchanges for a token at Alice's token endpoint.
  • Bob can now access Alice's private things.

Use-cases

Use-cases that inspired the development of this protocol:

  • be able to fetch private posts from someone's feed
  • don't rely on a "follow request" in order to do so
  • ...

Note: The most common use case thought of involves a private feed, but it does not inherently have to be a feed.

Brainstorming

In brainstorming some use cases, the following scenarios came up for possible use cases building on integrating multiple existing pieces.

  • Alice has a feed containing both public and private posts. By default, fetching it returns only the public posts. Alice decides she wants Bob to get the entire feed. Her site sends a ticket to Bob's ticket endpoint, which redeems it for a token that can access the feed.
    • How does Alice decide to send Bob a ticket? Not really important. It could be she monitors who is subscribed to her feed somehow, and wants to offer the full version. It could be Bob and Alice are friends and she invites him unsolicited.
    • What does Bob do with the token? Assuming that Bob's ticket endpoint is coupled together with his Microsub endpoint, and he's already subscribed to her feed, it should automatically start fetching the feed with the token to get the enhanced version with the private posts. If Bob wasn't already following, it would still get the token, but it would send the feed to a moderation queue or a dedicated Microsub channel for Bob to decide how to handle it.
  • If Alice has a single piece of restricted content she wants to share with Bob, it would work similarly to above, without the consideration of whether Bob was already privy to a different version of the content.
  • In another scenario, Carol wants to share private posts, but not a specific private post. She can opt to create a form on her site that send tickets to anyone who authenticates to it using IndieAuth, and then subsequently decide internally what content each user represented by the token gets. This is effectively giving everyone a login into your site.

Protocol

Step 1: Decide to issue an access token

Alice has choosen to share private things with Bob.

This is in contrast to a mechanism of advertising the fact that there may be private/protected content at a URL by using something like a WWW-Authenticate header. By indicating there may be more to see at a URL, that itself is leaking information.

The decision to share could be triggered by Bob notifying Alice that he is following Alice, or it could be without any affirmative action on Bob's part. This isn't strictly necessary but may provide a better user experience for granting these tokens.

  • TODO: Expand on methods of Bob notifying Alice could be a follow post, or some other protocol, but is not related to authentication or required.


Why not send the access token directly?

When you send a ticket, you are sending an unsolicited payload to the receiver. The ticket is not requested by the receiver, so you cannot guarantee they will be protecting it if they aren't expecting it. (It may be logged in intermediate proxy servers, written to log files on the server, etc.) If the receiver supports receiving tickets, then they will be explicitly requesting an access token by exchanging the ticket, so you can be more confident they will take measures to protect the access token. This way the access token is only delivered via an explicitly requested HTTPS connection to your server.

Additionally, given some IndieAuth servers don't support expiration of tokens(despite it being a recommendation), this could allow permanent access to protected data, which is not ideal.

Step 2: Issue an access token

Alice has decided to send an access token to Bob. (Either because Alice decided to out of the blue, or because Alice noticed Bob's follow notification.)

Create the IndieAuth ticket

Alice generates a short-lived ticket which will last approximately a minute at most. The reason for short-lived is that you are sending something unsolicited to someone and it is safer to send something short-lived and single use, and require action to retrieve the actual token.

Alice discovers the ticket endpoint of the subject. See #Discovery


Alice makes a POST request to the ticket endpoint. This is basically saying "if you wanted to fetch this as this person and see private stuff, here's a ticket you can use to get an access token".

  • ticket - a random string that can be redeemed for an access token
  • resource - the access token will work at this URL
  • subject - the access token should be used when acting on behalf of this URL
POST https://auth.example.org/ticket
     Content-Type: application/x-www-form-urlencoded

ticket=32985723984723985792834
&resource=https://alice.example.com/private/
&subject=https://bob.example.org


When a ticket is sent, if there is no problem with the request, the ticket endpoint MUST return an HTTP 200 OK code or HTTP 202 Accepted if it is going to asynchronously make the token request.

Redeem the ticket for an access token

Bob's ticket endpoint redeems the ticket for an access token

The ticket endpoint makes a GET or HEAD request to discover the token endpoint of the resource, https://alice.example.com/private/, searching for an HTTP Link element or a HTML <link> element with the appropriate rel value for the IndieAuth metadata endpoint, indieauth-metadata or fallback to the older token_endpoint.

The ticket endpoint makes a POST request to the token endpoint to exchange the ticket for an access token. The POST request contains the following parameters:

  • grant_type=ticket
  • ticket - The ticket to be redeemed

The IndieAuth spec does not currently address the issuance of resource-limited tokens. The discussion for that is at https://github.com/indieweb/indieauth/issues/82. Regardless of this adoption, if a token endpoint wishes to support the ticket grant type, then it MUST support the issuance of resource-limited tokens.

Should this also include client_id? https://github.com/indieweb/indieauth/issues/85

Example
POST https://alice.example.com/token
  Content-type: application/x-www-form-urlencoded
  Accept: application/json

  grant_type=ticket
  &ticket=32985723984723985792834

Response is an access token as specified in the IndieAuth Spec.

Step 3: Use the access token

Now Bob's authorization endpoint has the remote access token that could be used to fetch Alice's feed.

How to get it to the reader or the webmention endpoint verifier is up to those implementations, it may be internal, or may use another spec to coordinate.

Notes

The current implementation expects that all pages that could be deemed as a resource would have either the newer rel=indieauth-metadata or the older but still in use rel=token_endpoint

Advantages:

Discovery

A ticket endpoint can be discovered by fetching the URL of the subject and looking for the indieauth-metadata rel values as described in the IndieAuth Discovery.

The client fetches the metadata document and finds the ticket_endpoint property in the JSON body.

Some ticket endpoints may be advertised by a separate link header for those implemented prior to the addition of the indieauth-metadata endpoint, however, any IndieAuth implementation that supports a metadata endpoint SHOULD NOT advertise the ticket endpoint separately.

Token Issuing

How a website decides to issue tokens does not need to be defined by this spec.

Aaron Parecki created an interface to be able to send tickets to arbitrary URLs, and shows the token info after the ticket has been redeemed.

aaronpk-ticket-admin.png

Martijn van der Ven created a public interface on the token_endpoint where arbitrary homepage URLs can be given for anyone to receive a token.

Screenshot 2021-07-05 at 07.07.16.png

Proposed mechanism for requesting a ticket

https://github.com/indieweb/indieauth/issues/87

In order to request a ticket, a POST request would be made, indicating the subject is interested in accessing private content. How a website decides whether to provide a ticket in this case, and what resources it would unlock does not need to be defined by this spec.

In responding to a request, the endpoint would take the same approach as the webmention spec. Returning a 201, 202, or 400/500 for user and server errors respectively. The endpoint need not reveal whether it has chosen to issue a ticket, as the ticket endpoint would receive or not receive one as appropriate.


Open questions

See discussion on GitHub

  • Should it be assumed that the ticket endpoint will automatically redeem all tokens? It's technically an implementation detail, not a requirement of the spec, but witht he amount of time the ticket is valid, this seems a good move. Assuming the token endpoint supports revocation.
  • Where does the ticket endpoint go looking for the token endpoint? Currently the only thing it is sent that it can act on is the resource value. If that is also supposed to function as sort of a root URL of resources it gives access to, is it correct to assume the token endpoint can be discovered at that exact URL? (See first open Q.)
    • Martijn van der Ven ended up setting the resource as their root domain, which made it impossible to go get a token with the token endpoint only discoverable from the /martijn/ path. This was because of the assumption that resource was like realm in that it could be anything, but that stopped the ticket endpoint David Shanske was writing from ever redeeming. Short discussion in chat.
    • Something that can be fixed by providing a specific iss/issuer value along with the resource in the POST to the ticket endpoint?
      •   Jamie Tanna was wondering about the iss matching the issuer of the token (i.e. the IndieAuth server's URL) but agrees with Martijn van der Ven's point about it being in the initial POST to the ticket endpoint, and matching the identity URL of the user who is providing access
      •   Jamie Tanna's POC requires the issuer parameter
    • It was pointed out that by putiting the token endpoint header on a resource URL, you may be indicating there is something there. For example, you choose to have your private pages return 404. Then how does the ticket endpoint discover the token endpoint? As above, it should return a me/iss/issuer parameter
      • This indicates a few different use cases for granting tickets; it seems that some people want to generate tickets for a specific resource (e.g. a private post) sent securely to specific recipients, whereas other people want to generate tickets for being able to subscribe to a feed or otherwise retrieve data in a logged-in state. The original TicketAuth draft was to support the latter; do we also need to support the former? If resource points to specific private blog entries, that implies that it's up to the publisher to specifically send push notifications about all private content to all recipients, which has a lot of far-reaching implications.
  • Should we make it clear that multiple resources could be granted from a single ticket? Following RFC8707 would make it possible to do so
    •   Jamie Tanna's receiver supports resource and resource[]
  • Would it make sense to have resource for specific items, realm for blanket grants for an entire website/URL prefix/etc., and issuer for where to look for the token endpoint as an override if the endpoint can't be determined from resource/realm?
  • How to handle non-canonical/redirecting profile URLs? Since the ticket itself never goes through the full IndieAuth flow, the granter can't get the canonical identity URL from the authorization_endpoint.
    • As of this change in Publ, if Publ gets a ticket request for a page with a rel="canonical", it forwards the request to the canonical page. No trust is assumed based on the original requesting URL, and the ticket only goes to the canonical URL's declared endpoint.

IndieWeb Examples

Martijn van der Ven

As of 2021-07-04 (at 21:22 UTC), Martijn van der Ven has a token endpoint with the ability for anyone to request a ticket. It is accessible through https://vanderven.se/martijn/token/.

As of 2021-07-10 (Create Day), the homepage at https://vanderven.se/martijn/ will show a welcome message and an alternative photo when a valid Bearer token is send in the Authorization header.

Please treat the whole thing as experimental, and feel free to test your own endpoints against it!

Tokens created through there are meant for the entire domain (the resource is https://vanderven.se/) and have no scope set. They are purely to identify someone as their URL. Because of the experimental phase of this spec, tokens are kept to short life times (3 days).

  • Special: while requesting tickets is declared out-of-scope for this extension, the way it is implemented here follows the pattern from IndieAuth’s Token Revocation. A POST with action=ticket triggers the sending of a ticket.

As of 2022-09-04 (IWC Berlin), the source is available as a GitHub Gist.

David Shanske

As of 2021-07-04, David Shanske has a proof of concept ticket endpoint on his test site that can receive tickets and redeem the associated token and store it. As of 2021-07-10, it has a management interface but no redemption methodology.

Jamie Tanna

As of 2021-07-07,   Jamie Tanna has created a POC ticket endpoint which is Open Source and deployed to Heroku for anyone else to use it.

This implementation requires an issuer to reference the profile URL of the user who's token_endpoint is to be used for the ticket exchange.

This returns the token exchange body to the caller, and logs some information, but not the granted access token (currently), nor does it store it.

It does not yet utilize it for anything or have an interface to do so.

Jamie is currently using this on his testing identity.

fluffy

As of 2021-07-08, fluffy has added a token granting endpoint to Publ, which can be tested at a publ test instance. It supports the following TicketAuth login flows:

The resulting token can be tested on the human-readable profile page or by sending a token verification request to https://dev.beesbuzz.biz/_tokens.

This is also available on fluffy's personal site; see the user profile page for things to experiment with (including manually-generated tokens).

aaronpk

As of 2021-07-10, Aaron Parecki has implemented both sending and receiving tokens on a standalone test website.

See Also