Ticketing | April 2022 | |
Somers | Experimental | [Page] |
This document defines new protocols for use with IndieAuth(an extension to OAuth 2.0) by defining how to request ("please push"), deposit ("push"), and grant ("exchange for a bearer token") tickets between two parties. It further defines an new protocol to orchestrate the aforementioned to allow a third-party to act on-behalf-of the first party at the second-party. Use cases are provided.¶
This document defines new protocols for use with [IndieAuth] (an extension to OAuth 2.0 [RFC6749]) by defining flows between participants that directly or indirectly use tickets as an instrument to facilitate the following activities:¶
These activities are implemented respectively by the following flows:¶
The participants are:¶
In this case, Carol is playing the role of Felicity who is a feed reader.¶
Bob makes available feed-oriented resources which can be used by Alice to read resources recently published on his site. Bob tells Alice's authorization server the location of the feed, which then tells Felicity to subscribe to it.¶
This to be achieved when:¶
In this case, Carol is playing the role of Rachel, an impersonator, who only does so with a permissive and in a non-malicious manner.¶
Alice wants to have Rachel read private resources that Bob makes available to her. Bob does not know Rachel but Rachel can impersonate Alice so she can read things on-behalf-of Alice.¶
To achieve this the goal is the acquisition of an authorization code (Bearer token) across the security boundary of three parties (subject, audience, and actor/impersonator).¶
It should be stressed that this should happen without any action needed by the subject (it is "hands-off"), who also retaining agency over obtaining and passing token-based authorization codes to their chosen actor and that no preexisting relationship is needed between audience and actor.¶
This to be achieved when:¶
In this case, Carol performs a dual role (she is Felicity-Rachel): the ability to not only read feeds (the Felicity role), which themselves may be a protect resource, but also any protected resources in the feed, by impersonating Alice as necessary (the Rachel role).¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
This specification uses the terms "as metadata" and "user profile URL" defined by [IndieAuth], the terms "access token", "authorization server", "authorization endpoint", "authorization request", "client", "resource server", and "token endpoint" defined by The OAuth 2.0 Authorization Framework [RFC6749], the terms "delegation" and "security token service" defined by [RFC8693] the term "bearer token" defined by [RFC6750]¶
This specification defines the following terms:¶
Where examples of protocol messages are given, the payload has been formatted for presentation and is not a true representation of what is the wire data: for form-urlencoded payloads URL-encoding has not been done and additional white-space and line-breaks are shown between key-value pairs to aid readability; similarly for JSON payloads.¶
This specification defines new protocol flows around the use of tickets between participants in the IndieAuth universe:¶
The following table summarizes which participant/system is responsible for implementing which side of each ticketing flow.¶
ticketing flow | client | server |
---|---|---|
(W) ticket wanted | subject as | audience as |
(D) ticket deposit | audience as | subject as |
(X) ticket grant | subject as | audience as |
(O) ac-obo grant | actor | subject as |
Each protocol flow follows an archetypal pattern, as illustrated in Figure 3, between an initiator (the client-side of an HTTP request) and a target (the sever-side of an HTTP response):¶
The client needs to discover the endpoint where the request needs to be made.¶
For "subject":¶
A subject is identified by a user profile URL which is their canonical homepage in the world wide web at a domain which is unique to them and accessible by either the http or https scheme as specified in section 3.1 of [IndieAuth].¶
It is RECOMMENDED that a profile URL with a http scheme be considered unacceptable due toSection 7.¶
The client undertakes discovery as specified in Section 4.1 of [IndieAuth] against the user profile URL.¶
For "audience":¶
Do discovery for "audience" as detailed in Section 4.1 of [IndieAuth]¶
The client makes a request to the target endpoint using the HTTP "POST" method. Parameters are included in the HTTP request entity-body using the "application/x-www-form-urlencoded" format with a character encoding of UTF-8 as described in Appendix B of [RFC6749].¶
The parameters are detailed for each flow in this specification.¶
When an server receives a request it performs the following steps:¶
A successful response is constructed by adding the result parameters to the entity-body of the HTTP response using the "application/json" media type, as specified by [RFC8259], and an HTTP 202 status code or other applicable code. The result parameters are serialized into a JavaScript Object Notation (JSON) structure by adding each parameter at the top level. Parameter names and string values are included as JSON strings. Numerical values are included as JSON numbers. The order of parameters does not matter and can vary.¶
The result parameters are detailed for each flow in this specification.¶
If the request is not valid or is unacceptable based on policy or there is a problem when processing the request the authorization server MUST construct an error response, as specified in Section 5.2 of [RFC6749]. The value of the "error" parameter MUST be the "invalid_request" error code or other values as detailed for each flow in this specification.¶
The authorization server MAY include additional information regarding the reasons for the error using the "error_description" as discussed in Section 5.2 of [RFC6749].¶
Other HTTP status codes may also be used as appropriate, for example:¶
The ticket is an opaque string. It MUST be at lest 16 characters in length and no more than 512 characters.¶
When an authorization server generates a ticket it is HIGHLY RECOMMENDED that it is a version 4 UUID generated as specified in Section 4.4 of [RFC4122].¶
If an authorization server wants to generate a structured ticket it MUST not be a JWT due to Section 7 and its content MUST respect Section 8.¶
The following authorization server metadata [RFC8414] parameters are introduced to signal an authorization server's capability and policy with respect to which aspects of ticketing it supports.¶
If an authorization server implements OAuth Introspection [RFC7662] it MAY consider a ticket to be like a token and allow it to be introspected with "token_type__hint=ticket" as per Section 1 of [RFC7662].¶
Example token introspection request against a ticket:¶
POST /as/token_introspect HTTP/1.1 Host: https://bob.example.com Content-type: application/x-www-form-urlencoded; charset=utf-8 Accept: application/json token=TICKET1234 &token_type_hint=ticket¶
Example token introspection response against a ticket:¶
HTTP 1.1 Content-Type: application/json Cache: no-cache, no-store { "active" : false, "scope": "read", "client_id": "https://bob.example" "username": "rachel obo alice", "token_type": "ticket", "iat": "1648710000", "exp": "1648992070", "sub": "https://alice.example/", "aud": "https://bob.example/". "iss": "https://bob.example/as" }¶
The target endpoint MUST use the "https" scheme per Section 7.¶
The client makes a request as specified in Section 2.4 to the target endpoint with the following parameters:¶
Example ticket wanted request:¶
POST /as/ticket_wanted HTTP/1.1 Host: https://bob.example.com Content-type: application/x-www-form-urlencoded; charset=utf-8 Accept: application/json action=ticket &subject=https://alice.example.com/¶
The request is processed as specified in Section 2.5 and the specific work to be performed for ticket wanted flow is:¶
The response will be as specified in Section 2.6 and there are no response parameters so the body of the response is at the discretion of the authorization server.¶
It is RECOMMEND that http content negotiation as specified in section 5.3 of [RFC7231] is undertaken and the server responds to following media types accordingly (defaulting to "application/json"):¶
Example ticket wanted response with content-negotiated JSON body:¶
HTTP 1.1 Content-Type: application/json Cache: no-cache, no-store { "subject" : "https://alice.example.com/" }¶
<subject>
"¶
Example ticket wanted response with content negotiated text/plain body:¶
HTTP 1.1 Content-Type: text/plain Cache: no-cache, no-store Received Ticket Wanted Request for https://alice.example.com/¶
If an error response is warranted it MUST be as per Section 2.7.¶
An error response MUST only be returned if there is a problem with the request parameters per se (for example missing or malformed).¶
The server MUST NOT return an error response if the subject is not known because that would leak that the publisher does not have a relationship with the subject, and conversely that it does (which would be an issue if the request did not originate from the subject but from a malicious client).¶
The target endpoint MUST use the https schema per Section 7.¶
The client makes a request as specified in Section 2.4 to the target endpoint with the following parameters:¶
Example ticket deposit request:¶
POST /as/ticket_wanted HTTP/1.1 Host: bob.example.com Content-type: application/x-www-form-urlencoded; charset=utf-8 Accept: application/json, text/plain subject=https://alice.example.com/ resource=https://bob.example.com/ ticket=TICKET1234567890¶
Example ticket deposit request hinting there is a feed that the subject can subscribe to:¶
POST /as/ticket_wanted HTTP/1.1 Host: bob.example.com Content-type: application/x-www-form-urlencoded; charset=utf-8 Accept: application/json, text/plain subject=https://alice.example.com/ resource=https://bob.example.com/feeds/ ticket=TICKET1234567890¶
The request is processed as specified in Section 2.5 and the specific work to be performed for ticket deposit flow is:¶
Optionally, perform ticket grant type flow with the following parameters:¶
The authorization server MUST respond as specified in Section 2.6 with the caveat that a response body is optional, but if provided the parameters are:¶
Example ticket deposit successful response:¶
HTTP/1.1 202 Accepted Content-Type: application/json Cache-Control: no-cache, no-store { "ticket_deposited" : "TICKET1234567890" }¶
A server MAY use content negotiation, and respond to "text/plain" with the a body containing the parameter as a key "=" value.¶
Example ticket deposit successful response with content-negotiated text/plain body:¶
HTTP/1.1 202 Accepted Content-Type: text/plain Cache-Control: no-cache, no-store ticket_deposited=TICKET1234567890¶
For content negotiation evaluating to "text/html" the server can respond with any body that it likes.¶
If an error response is warranted it MUST be as per Section 2.7.¶
The client makes a request as specified in Section 2.4 to the target endpoint with the following parameters:¶
Example ticket grant request:¶
POST /as/token HTTP/1.1 Host: bob.example.com Content-type: application/x-www-form-urlencoded; charset=utf-8 Accept: application/json, text/plain grant_type=ticket &ticket=TICKET1234567890¶
The request is processed as specified in Section 2.5 and the specific work to be performed for ticket grant flow is:¶
The response is an access token response as specified in section 5.3.3 of [IndieAuth].¶
Example response to a ticket grant request:¶
HTTP 1.1 Content-Type: application/json Cache: no-cache, no-store { "access_token" : "TOKEN1234567890", "token_type" : "Bearer", "expires_in" : 259200, "scope" : "read" }¶
If an error response is warranted it MUST be as per Section 2.7.¶
When the request is made, it MUST also include something which can be used to assure the receiver that it has come from the "client_id" provided. The client MUST NOT use more than one method in each request. The following methods be offered:¶
The client makes a request as specified in Section 2.4 to the target endpoint with the following parameters:¶
Example authorization code on-behalf-of grant request:¶
POST /as/token HTTP/1.1 Host: alice.example.com Content-type: application/x-www-form-urlencoded; charset=utf-8 Accept: application/json grant_type=authorization_code &requested_token_use=on_behalf_of &subject=https://alice.example.com/ &resource=https://bob.example.com/ &client_id=https://rachel.example.com/ &claim=CV123 &claim_type=pkce_verifier¶
The request is processed as specified in Section 2.5 and the specific work to be performed for authorization code on-behalf-of grant flow is:¶
If a successful response is warranted it MUST be as per Section 2.6 and the parameters correspond to this for a normal OAuth 2.0 response as specified in Section 5 of [RFC6749] but the following constraints:¶
Additional parameters MAY be included for implementation-specific reasons.¶
Example access token successful response:¶
HTTP 1.1 200 OK Content-type: application/json Cache-Control: no-cache, no-store { "access_token" : "AT1234" "token_type" : "Bearer" "expires_in" : 3600 "scope" : "read" "refresh_token": "RT1234" }¶
If an error response is warranted it MUST be as per Section 2.7.¶
The following alternative "error" values MUST be used instead of the generic "bad_request" in the following circumstances:¶
Much of the guidance from Section 10 of [RFC6749], the Security Considerations in The OAuth 2.0 Authorization Framework, is also applicable here. Furthermore, [RFC6819] provides additional security considerations for OAuth, and [I-D.ietf-oauth-security-topics] has updated security guidance based on deployment experience and new threats that have emerged since OAuth 2.0 was originally published.¶
If the ticket issued by an authorization server is a JWT particular attention should be paid to Section 5 of [RFC9068].¶
The use of JWTs as a ticket is not encouraged and implementors should use an opaque string.¶
Do NOT attempt to read tickets. No assumption should be made as to their format and they may or many not validate as a JWT. While reading tickets is a useful for debugging, implementations should not depend on this ability because tickets are opaque.¶
In addition, both delegation and impersonation introduce unique security issues. Any time one principal is delegated the rights of another principal, the potential for abuse is a concern. The use of the "scope" claim (in addition to other typical constraints such as a limited token lifetime) is suggested to mitigate potential for such abuse, as it restricts the contexts in which the delegated rights can be exercised.¶
For authorization code on-behalf-of grant flow, the relative agency of the subject is limited by the expiration time of the token issued. The agency can only be exercised when the subject's authorization server is requested to acquire a new token during this flow. Hence the limitation on the subject's agency is bounded by the age of the token from the audience that they forward to the actor. For this reason it is imperative that an audience issue tokens in response to this grant request with a sensibly short expiration time to ensure the subject can maintain agency over the actor.¶
Tickets and tokens employed in the context of the functionality described herein may contain privacy-sensitive information and, to prevent disclosure of such information to unintended parties, MUST only be transmitted over encrypted channels, such as Transport Layer Security (TLS).¶
Deployments SHOULD determine the minimally necessary amount of data and only include such information in issued tickets or tokens. In some cases, data minimization may be needed and this is of particular relevance when an authorization server is acting like an STS in authorization code on-behalf-of grant flow.¶
To indicate ticket grant flow is supported:¶
urn:indieweb.org:params:oauth:grant-type:ticket
¶
To signal that authorization code on-behalf-of grant flow is supported:¶
urn:indieweb.org:params:oauth:grant-type:on_behalf_of
¶
There are no IANA actions requested at this time.¶
If the subject has identified themselves to the actor as specified in Section 5.3.2 of [IndieAuth] various exchanges will have taken place between the subject's authorization server and the actor's authorization client during which a "code_verifier" is generated because IndieAuth mandates the use of PKCE as specified in [RFC7636]. The actor can use the "code_verifier" of the last successfully exchange with the subject's authorization server as claim that they are who they are on the basis that only they have this information and that the subject's authorization server can verify it. For this to be implemented:¶
This document stands on the shoulders of the members of the IndieWeb community for their work on [TicketAuth] and [AutoAuth] which provided inspiration for this document.¶
The following individuals directly or indirectly contributed ideas, feedback, and wording to this specification: @fluffy, @gwg, @zegnat.¶
[[ To be removed from the final specification ]] -00 * first draft¶