draft-ietf-oauth-token-binding-04.txt | draft-ietf-oauth-token-binding-05.txt | |||
---|---|---|---|---|
OAuth Working Group M. Jones | OAuth Working Group M. Jones | |||
Internet-Draft Microsoft | Internet-Draft Microsoft | |||
Intended status: Standards Track J. Bradley | Intended status: Standards Track B. Campbell | |||
Expires: January 4, 2018 B. Campbell | Expires: April 29, 2018 Ping Identity | |||
Ping Identity | J. Bradley | |||
Yubico | ||||
W. Denniss | W. Denniss | |||
July 3, 2017 | October 26, 2017 | |||
OAuth 2.0 Token Binding | OAuth 2.0 Token Binding | |||
draft-ietf-oauth-token-binding-04 | draft-ietf-oauth-token-binding-05 | |||
Abstract | Abstract | |||
This specification enables OAuth 2.0 implementations to apply Token | This specification enables OAuth 2.0 implementations to apply Token | |||
Binding to Access Tokens, Authorization Codes, and Refresh Tokens. | Binding to Access Tokens, Authorization Codes, Refresh Tokens, JWT | |||
This cryptographically binds these tokens to a client's Token Binding | Authorization Grants, and JWT Client Authentication. This | |||
key pair, possession of which is proven on the TLS connections over | cryptographically binds these tokens to a client's Token Binding key | |||
which the tokens are intended to be used. This use of Token Binding | pair, possession of which is proven on the TLS connections over which | |||
the tokens are intended to be used. This use of Token Binding | ||||
protects these tokens from man-in-the-middle and token export and | protects these tokens from man-in-the-middle and token export and | |||
replay attacks. | replay attacks. | |||
Status of This Memo | Status of This Memo | |||
This Internet-Draft is submitted in full conformance with the | This Internet-Draft is submitted in full conformance with the | |||
provisions of BCP 78 and BCP 79. | provisions of BCP 78 and BCP 79. | |||
Internet-Drafts are working documents of the Internet Engineering | Internet-Drafts are working documents of the Internet Engineering | |||
Task Force (IETF). Note that other groups may also distribute | Task Force (IETF). Note that other groups may also distribute | |||
working documents as Internet-Drafts. The list of current Internet- | working documents as Internet-Drafts. The list of current Internet- | |||
Drafts is at http://datatracker.ietf.org/drafts/current/. | Drafts is at https://datatracker.ietf.org/drafts/current/. | |||
Internet-Drafts are draft documents valid for a maximum of six months | Internet-Drafts are draft documents valid for a maximum of six months | |||
and may be updated, replaced, or obsoleted by other documents at any | and may be updated, replaced, or obsoleted by other documents at any | |||
time. It is inappropriate to use Internet-Drafts as reference | time. It is inappropriate to use Internet-Drafts as reference | |||
material or to cite them other than as "work in progress." | material or to cite them other than as "work in progress." | |||
This Internet-Draft will expire on January 4, 2018. | This Internet-Draft will expire on April 29, 2018. | |||
Copyright Notice | Copyright Notice | |||
Copyright (c) 2017 IETF Trust and the persons identified as the | Copyright (c) 2017 IETF Trust and the persons identified as the | |||
document authors. All rights reserved. | document authors. All rights reserved. | |||
This document is subject to BCP 78 and the IETF Trust's Legal | This document is subject to BCP 78 and the IETF Trust's Legal | |||
Provisions Relating to IETF Documents | Provisions Relating to IETF Documents | |||
(http://trustee.ietf.org/license-info) in effect on the date of | (https://trustee.ietf.org/license-info) in effect on the date of | |||
publication of this document. Please review these documents | publication of this document. Please review these documents | |||
carefully, as they describe your rights and restrictions with respect | carefully, as they describe your rights and restrictions with respect | |||
to this document. Code Components extracted from this document must | to this document. Code Components extracted from this document must | |||
include Simplified BSD License text as described in Section 4.e of | include Simplified BSD License text as described in Section 4.e of | |||
the Trust Legal Provisions and are provided without warranty as | the Trust Legal Provisions and are provided without warranty as | |||
described in the Simplified BSD License. | described in the Simplified BSD License. | |||
Table of Contents | Table of Contents | |||
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 | 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 | |||
1.1. Requirements Notation and Conventions . . . . . . . . . . 3 | 1.1. Requirements Notation and Conventions . . . . . . . . . . 3 | |||
1.2. Terminology . . . . . . . . . . . . . . . . . . . . . . . 3 | 1.2. Terminology . . . . . . . . . . . . . . . . . . . . . . . 3 | |||
2. Token Binding for Refresh Tokens . . . . . . . . . . . . . . 3 | 2. Token Binding for Refresh Tokens . . . . . . . . . . . . . . 4 | |||
2.1. Example Token Binding for Refresh Tokens . . . . . . . . 4 | 2.1. Example Token Binding for Refresh Tokens . . . . . . . . 4 | |||
3. Token Binding for Access Tokens . . . . . . . . . . . . . . . 6 | 3. Token Binding for Access Tokens . . . . . . . . . . . . . . . 7 | |||
3.1. Access Tokens Issued from the Authorization Endpoint . . 7 | 3.1. Access Tokens Issued from the Authorization Endpoint . . 8 | |||
3.1.1. Example Access Token Issued from the Authorization | 3.1.1. Example Access Token Issued from the Authorization | |||
Endpoint . . . . . . . . . . . . . . . . . . . . . . 8 | Endpoint . . . . . . . . . . . . . . . . . . . . . . 8 | |||
3.2. Access Tokens Issued from the Token Endpoint . . . . . . 9 | 3.2. Access Tokens Issued from the Token Endpoint . . . . . . 9 | |||
3.2.1. Example Access Token Issued from the Token Endpoint . 9 | 3.2.1. Example Access Token Issued from the Token Endpoint . 10 | |||
3.3. Protected Resource Token Binding Validation . . . . . . . 11 | 3.3. Protected Resource Token Binding Validation . . . . . . . 12 | |||
3.3.1. Example Protected Resource Request . . . . . . . . . 11 | 3.3.1. Example Protected Resource Request . . . . . . . . . 12 | |||
3.4. Representing Token Binding in JWT Access Tokens . . . . . 11 | 3.4. Representing Token Binding in JWT Access Tokens . . . . . 12 | |||
3.5. Representing Token Binding in Introspection Responses . . 12 | 3.5. Representing Token Binding in Introspection Responses . . 13 | |||
4. Token Binding for Authorization Codes . . . . . . . . . . . . 13 | 4. Token Binding Metadata . . . . . . . . . . . . . . . . . . . 14 | |||
4.1. Native Application Clients . . . . . . . . . . . . . . . 13 | 4.1. Token Binding Client Metadata . . . . . . . . . . . . . . 14 | |||
4.1.1. Code Challenge . . . . . . . . . . . . . . . . . . . 14 | 4.2. Token Binding Authorization Server Metadata . . . . . . . 14 | |||
4.1.1.1. Example Code Challenge . . . . . . . . . . . . . 14 | 5. Token Binding for Authorization Codes . . . . . . . . . . . . 15 | |||
4.1.2. Code Verifier . . . . . . . . . . . . . . . . . . . . 14 | 5.1. Native Application Clients . . . . . . . . . . . . . . . 15 | |||
4.1.2.1. Example Code Verifier . . . . . . . . . . . . . . 15 | 5.1.1. Code Challenge . . . . . . . . . . . . . . . . . . . 15 | |||
4.2. Web Server Clients . . . . . . . . . . . . . . . . . . . 15 | 5.1.1.1. Example Code Challenge . . . . . . . . . . . . . 16 | |||
4.2.1. Code Challenge . . . . . . . . . . . . . . . . . . . 16 | 5.1.2. Code Verifier . . . . . . . . . . . . . . . . . . . . 16 | |||
4.2.1.1. Example Code Challenge . . . . . . . . . . . . . 16 | 5.1.2.1. Example Code Verifier . . . . . . . . . . . . . . 17 | |||
4.2.2. Code Verifier . . . . . . . . . . . . . . . . . . . . 17 | 5.2. Web Server Clients . . . . . . . . . . . . . . . . . . . 17 | |||
4.2.2.1. Example Code Verifier . . . . . . . . . . . . . . 18 | 5.2.1. Code Challenge . . . . . . . . . . . . . . . . . . . 18 | |||
5. Phasing in Token Binding and Preventing Downgrade Attacks . . 18 | 5.2.1.1. Example Code Challenge . . . . . . . . . . . . . 18 | |||
6. Token Binding Metadata . . . . . . . . . . . . . . . . . . . 19 | 5.2.2. Code Verifier . . . . . . . . . . . . . . . . . . . . 19 | |||
6.1. Token Binding Client Metadata . . . . . . . . . . . . . . 19 | 5.2.2.1. Example Code Verifier . . . . . . . . . . . . . . 19 | |||
6.2. Token Binding Authorization Server Metadata . . . . . . . 20 | 6. Token Binding JWT Authorization Grants and Client | |||
6.3. Token Binding Protected Resource Metadata . . . . . . . . 20 | Authentication . . . . . . . . . . . . . . . . . . . . . . . 20 | |||
7. Security Considerations . . . . . . . . . . . . . . . . . . . 20 | 6.1. JWT Format and Processing Requirements . . . . . . . . . 20 | |||
8. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 20 | 6.2. Token Bound JWTs for Client Authentication . . . . . . . 21 | |||
8.1. OAuth Dynamic Client Registration Metadata Registration . 20 | 6.3. Token Bound JWTs for as Authorization Grants . . . . . . 21 | |||
8.1.1. Registry Contents . . . . . . . . . . . . . . . . . . 21 | 7. Security Considerations . . . . . . . . . . . . . . . . . . . 22 | |||
8.2. OAuth Authorization Server Metadata Registration . . . . 21 | 7.1. Phasing in Token Binding . . . . . . . . . . . . . . . . 22 | |||
8.2.1. Registry Contents . . . . . . . . . . . . . . . . . . 21 | 7.2. Binding of Refresh Tokens . . . . . . . . . . . . . . . . 22 | |||
8.3. OAuth Protected Resource Metadata Registration . . . . . 21 | 8. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 23 | |||
8.3.1. Registry Contents . . . . . . . . . . . . . . . . . . 21 | 8.1. OAuth Dynamic Client Registration Metadata Registration . 23 | |||
8.1.1. Registry Contents . . . . . . . . . . . . . . . . . . 23 | ||||
8.4. PKCE Code Challenge Method Registration . . . . . . . . . 22 | 8.2. OAuth Authorization Server Metadata Registration . . . . 24 | |||
8.4.1. Registry Contents . . . . . . . . . . . . . . . . . . 22 | 8.2.1. Registry Contents . . . . . . . . . . . . . . . . . . 24 | |||
9. References . . . . . . . . . . . . . . . . . . . . . . . . . 22 | 8.3. PKCE Code Challenge Method Registration . . . . . . . . . 24 | |||
9.1. Normative References . . . . . . . . . . . . . . . . . . 22 | 8.3.1. Registry Contents . . . . . . . . . . . . . . . . . . 24 | |||
9.2. Informative References . . . . . . . . . . . . . . . . . 24 | 9. Token Endpoint Authentication Method Registration . . . . . . 24 | |||
Appendix A. Acknowledgements . . . . . . . . . . . . . . . . . . 24 | 9.1. Registry Contents . . . . . . . . . . . . . . . . . . . . 25 | |||
Appendix B. Open Issues . . . . . . . . . . . . . . . . . . . . 24 | 10. Sub-Namespace Registrations . . . . . . . . . . . . . . . . . 25 | |||
Appendix C. Document History . . . . . . . . . . . . . . . . . . 25 | 10.1. Registry Contents . . . . . . . . . . . . . . . . . . . 25 | |||
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 27 | 11. References . . . . . . . . . . . . . . . . . . . . . . . . . 25 | |||
11.1. Normative References . . . . . . . . . . . . . . . . . . 25 | ||||
11.2. Informative References . . . . . . . . . . . . . . . . . 27 | ||||
Appendix A. Acknowledgements . . . . . . . . . . . . . . . . . . 28 | ||||
Appendix B. Document History . . . . . . . . . . . . . . . . . . 28 | ||||
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 30 | ||||
1. Introduction | 1. Introduction | |||
This specification enables OAuth 2.0 [RFC6749] implementations to | This specification enables OAuth 2.0 [RFC6749] implementations to | |||
apply Token Binding (TLS Extension for Token Binding Protocol | apply Token Binding (TLS Extension for Token Binding Protocol | |||
Negotiation [I-D.ietf-tokbind-negotiation], The Token Binding | Negotiation [I-D.ietf-tokbind-negotiation], The Token Binding | |||
Protocol Version 1.0 [I-D.ietf-tokbind-protocol] and Token Binding | Protocol Version 1.0 [I-D.ietf-tokbind-protocol] and Token Binding | |||
over HTTP [I-D.ietf-tokbind-https]) to Access Tokens, Authorization | over HTTP [I-D.ietf-tokbind-https]) to Access Tokens, Authorization | |||
Codes, and Refresh Tokens. This cryptographically binds these tokens | Codes, Refresh Tokens, JWT Authorization Grants, and JWT Client | |||
to a client's Token Binding key pair, possession of which is proven | Authentication. This cryptographically binds these tokens to a | |||
on the TLS connections over which the tokens are intended to be used. | client's Token Binding key pair, possession of which is proven on the | |||
This use of Token Binding protects these tokens from man-in-the- | TLS connections over which the tokens are intended to be used. This | |||
middle and token export and replay attacks. | use of Token Binding protects these tokens from man-in-the-middle and | |||
token export and replay attacks. | ||||
1.1. Requirements Notation and Conventions | 1.1. Requirements Notation and Conventions | |||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", | |||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and | "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and | |||
"OPTIONAL" in this document are to be interpreted as described in RFC | "OPTIONAL" in this document are to be interpreted as described in RFC | |||
2119 [RFC2119]. | 2119 [RFC2119]. | |||
1.2. Terminology | 1.2. Terminology | |||
skipping to change at page 4, line 48 ¶ | skipping to change at page 5, line 11 ¶ | |||
Token Bound refresh token might look like, along with some details of | Token Bound refresh token might look like, along with some details of | |||
the involved processing. Token Binding of refresh tokens is most | the involved processing. Token Binding of refresh tokens is most | |||
useful for native application clients so the example has protocol | useful for native application clients so the example has protocol | |||
elements typical of a native client flow. Extra line breaks in all | elements typical of a native client flow. Extra line breaks in all | |||
examples are for display purposes only. | examples are for display purposes only. | |||
A native application client makes the following access token request | A native application client makes the following access token request | |||
with an authorization code using a TLS connection where Token Binding | with an authorization code using a TLS connection where Token Binding | |||
has been negotiated. A PKCE "code_verifier" is included because use | has been negotiated. A PKCE "code_verifier" is included because use | |||
of PKCE is considered best practice for native application clients | of PKCE is considered best practice for native application clients | |||
[I-D.ietf-oauth-native-apps]. The base64url-encoded representation | [BCP212]. The base64url-encoded representation of the exported | |||
of the exported keying material (EKM) from that TLS connection is | keying material (EKM) from that TLS connection is | |||
"p6ZuSwfl6pIe8es5KyeV76T4swZmQp0_awd27jHfrbo", which is needed to | "p6ZuSwfl6pIe8es5KyeV76T4swZmQp0_awd27jHfrbo", which is needed to | |||
validate the Token Binding Message. | validate the Token Binding Message. | |||
POST /as/token.oauth2 HTTP/1.1 | POST /as/token.oauth2 HTTP/1.1 | |||
Host: server.example.com | Host: server.example.com | |||
Content-Type: application/x-www-form-urlencoded | Content-Type: application/x-www-form-urlencoded | |||
Sec-Token-Binding: AIkAAgBBQGto7hHRR0Y5nkOWqc9KNfwW95dEFmSI_tCZ_Cbl | Sec-Token-Binding: AIkAAgBBQGto7hHRR0Y5nkOWqc9KNfwW95dEFmSI_tCZ_Cbl | |||
7LWlt6Xjp3DbjiDJavGFiKP2HV_2JSE42VzmKOVVV8m7eqAAQOKiDK1Oi0z6v4X5B | 7LWlt6Xjp3DbjiDJavGFiKP2HV_2JSE42VzmKOVVV8m7eqAAQOKiDK1Oi0z6v4X5B | |||
P7uc0pFestVZ42TTOdJmoHpji06Qq3jsCiCRSJx9ck2fWJYx8tLVXRZPATB3x6c24 | P7uc0pFestVZ42TTOdJmoHpji06Qq3jsCiCRSJx9ck2fWJYx8tLVXRZPATB3x6c24 | |||
aY0ZEAAA | aY0ZEAAA | |||
skipping to change at page 12, line 42 ¶ | skipping to change at page 13, line 35 ¶ | |||
For a token bound access token, the hash of the Token Binding ID to | For a token bound access token, the hash of the Token Binding ID to | |||
which the token is bound is conveyed to the protected resource as | which the token is bound is conveyed to the protected resource as | |||
meta-information in a token introspection response. The hash is | meta-information in a token introspection response. The hash is | |||
conveyed using same structure as the token binding hash confirmation | conveyed using same structure as the token binding hash confirmation | |||
method, described in Section 3.4, as a top-level member of the | method, described in Section 3.4, as a top-level member of the | |||
introspection response JSON. The protected resource compares that | introspection response JSON. The protected resource compares that | |||
token binding hash to a hash of the provided Token Binding ID and | token binding hash to a hash of the provided Token Binding ID and | |||
rejects the request, if they do not match. | rejects the request, if they do not match. | |||
The following is an example of an introspection response for an | The following is an example of an introspection response for an | |||
active token bound access token with an "tbh" token binding hash | active token bound access token with a "tbh" token binding hash | |||
confirmation method. | confirmation method. | |||
HTTP/1.1 200 OK | HTTP/1.1 200 OK | |||
Content-Type: application/json | Content-Type: application/json | |||
{ | { | |||
"active": true, | "active": true, | |||
"iss": "https://server.example.com", | "iss": "https://server.example.com", | |||
"aud": "https://resource.example.org", | "aud": "https://resource.example.org", | |||
"sub": "brian@example.com" | "sub": "brian@example.com" | |||
"iat": 1467324320, | "iat": 1467324320, | |||
"exp": 1467324920, | "exp": 1467324920, | |||
"cnf":{ | "cnf":{ | |||
"tbh": "7NRBu9iDdJlYCTOqyeYuLxXv0blEA-yTpmGIrAwKAws" | "tbh": "7NRBu9iDdJlYCTOqyeYuLxXv0blEA-yTpmGIrAwKAws" | |||
} | } | |||
} | } | |||
Figure 13: Example Introspection Response for a Token Bound Access | Figure 13: Example Introspection Response for a Token Bound Access | |||
Token | Token | |||
4. Token Binding for Authorization Codes | 4. Token Binding Metadata | |||
4.1. Token Binding Client Metadata | ||||
Clients supporting Token Binding that also support the OAuth 2.0 | ||||
Dynamic Client Registration Protocol [RFC7591] use these metadata | ||||
values to declare their support for Token Binding of access tokens | ||||
and refresh tokens: | ||||
client_access_token_token_binding_supported | ||||
OPTIONAL. Boolean value specifying whether the client supports | ||||
Token Binding of access tokens. If omitted, the default value is | ||||
"false". | ||||
client_refresh_token_token_binding_supported | ||||
OPTIONAL. Boolean value specifying whether the client supports | ||||
Token Binding of refresh tokens. If omitted, the default value is | ||||
"false". Authorization servers MUST NOT Token Bind refresh tokens | ||||
issued to a client that does not support Token Binding of refresh | ||||
tokens, but MAY reject requests completely from such clients if | ||||
token binding is required by authorization server policy by | ||||
returning an OAuth error response. | ||||
4.2. Token Binding Authorization Server Metadata | ||||
Authorization servers supporting Token Binding that also support | ||||
OAuth 2.0 Authorization Server Metadata [OAuth.AuthorizationMetadata] | ||||
use these metadata values to declare their support for Token Binding | ||||
of access tokens and refresh tokens: | ||||
as_access_token_token_binding_supported | ||||
OPTIONAL. Boolean value specifying whether the authorization | ||||
server supports Token Binding of access tokens. If omitted, the | ||||
default value is "false". | ||||
as_refresh_token_token_binding_supported | ||||
OPTIONAL. Boolean value specifying whether the authorization | ||||
server supports Token Binding of refresh tokens. If omitted, the | ||||
default value is "false". | ||||
5. Token Binding for Authorization Codes | ||||
There are two variations for Token Binding of an authorization code. | There are two variations for Token Binding of an authorization code. | |||
One is appropriate for native application clients and the other for | One is appropriate for native application clients and the other for | |||
web server clients. The nature of where the various components | web server clients. The nature of where the various components | |||
reside for the different client types demands different methods of | reside for the different client types demands different methods of | |||
Token Binding the authorization code so that it is bound to a Token | Token Binding the authorization code so that it is bound to a Token | |||
Binding key on the end user's device. This ensures that a lost or | Binding key on the end user's device. This ensures that a lost or | |||
stolen authorization code cannot be successfully utilized from a | stolen authorization code cannot be successfully utilized from a | |||
different device. For native application clients, the code is bound | different device. For native application clients, the code is bound | |||
to a Token Binding key pair that the native client itself possesses. | to a Token Binding key pair that the native client itself possesses. | |||
For web server clients, the code is bound to a Token Binding key pair | For web server clients, the code is bound to a Token Binding key pair | |||
on the end user's browser. Both variations utilize the extensible | on the end user's browser. Both variations utilize the extensible | |||
framework of Proof Key for Code Exchange (PKCE) [RFC7636], which | framework of Proof Key for Code Exchange (PKCE) [RFC7636], which | |||
enables the client to show possession of a certain key when | enables the client to show possession of a certain key when | |||
exchanging the authorization code for tokens. The following | exchanging the authorization code for tokens. The following | |||
subsections individually describe each of the two PKCE methods | subsections individually describe each of the two PKCE methods | |||
respectively. | respectively. | |||
4.1. Native Application Clients | 5.1. Native Application Clients | |||
This section describes a PKCE method suitable for native application | This section describes a PKCE method suitable for native application | |||
clients that cryptographically binds the authorization code to a | clients that cryptographically binds the authorization code to a | |||
Token Binding key pair on the client, which the client proves | Token Binding key pair on the client, which the client proves | |||
possession of on the TLS connection during the access token request | possession of on the TLS connection during the access token request | |||
containing the authorization code. The authorization code is bound | containing the authorization code. The authorization code is bound | |||
to the Token Binding ID that the native application client uses to | to the Token Binding ID that the native application client uses to | |||
resolve the authorization code at the token endpoint. This binding | resolve the authorization code at the token endpoint. This binding | |||
ensures that the client that made the authorization request is the | ensures that the client that made the authorization request is the | |||
same client that is presenting the authorization code. | same client that is presenting the authorization code. | |||
4.1.1. Code Challenge | 5.1.1. Code Challenge | |||
As defined in Proof Key for Code Exchange [RFC7636], the client sends | As defined in Proof Key for Code Exchange [RFC7636], the client sends | |||
the code challenge as part of the OAuth 2.0 authorization request | the code challenge as part of the OAuth 2.0 authorization request | |||
with the two additional parameters: "code_challenge" and | with the two additional parameters: "code_challenge" and | |||
"code_challenge_method". | "code_challenge_method". | |||
For this Token Binding method of PKCE, "TB-S256" is used as the value | For this Token Binding method of PKCE, "TB-S256" is used as the value | |||
of the "code_challenge_method" parameter. | of the "code_challenge_method" parameter. | |||
The value of the "code_challenge" parameter is the base64url encoding | The value of the "code_challenge" parameter is the base64url encoding | |||
skipping to change at page 14, line 30 ¶ | skipping to change at page 16, line 23 ¶ | |||
endpoint. Note that, prior to making the authorization request, the | endpoint. Note that, prior to making the authorization request, the | |||
client may need to establish a TLS connection between itself and the | client may need to establish a TLS connection between itself and the | |||
authorization server's token endpoint in order to establish the | authorization server's token endpoint in order to establish the | |||
appropriate Token Binding ID. | appropriate Token Binding ID. | |||
When the authorization server issues the authorization code in the | When the authorization server issues the authorization code in the | |||
authorization response, it associates the code challenge and method | authorization response, it associates the code challenge and method | |||
values with the authorization code so they can be verified later when | values with the authorization code so they can be verified later when | |||
the authorization code is presented in the access token request. | the authorization code is presented in the access token request. | |||
4.1.1.1. Example Code Challenge | 5.1.1.1. Example Code Challenge | |||
For example, a native application client sends an authorization | For example, a native application client sends an authorization | |||
request by sending the user's browser to the authorization endpoint. | request by sending the user's browser to the authorization endpoint. | |||
The resulting HTTP request looks something like the following (with | The resulting HTTP request looks something like the following (with | |||
extra line breaks for display purposes only). | extra line breaks for display purposes only). | |||
GET /as/authorization.oauth2?response_type=code | GET /as/authorization.oauth2?response_type=code | |||
&client_id=example-native-client-id&state=oUC2jyYtzRCrMyWrVnGj | &client_id=example-native-client-id&state=oUC2jyYtzRCrMyWrVnGj | |||
&code_challenge=rBlgOyMY4teiuJMDgOwkrpsAjPyI07D2WsEM-dnq6eE | &code_challenge=rBlgOyMY4teiuJMDgOwkrpsAjPyI07D2WsEM-dnq6eE | |||
&code_challenge_method=TB-S256 HTTP/1.1 | &code_challenge_method=TB-S256 HTTP/1.1 | |||
Host: server.example.com | Host: server.example.com | |||
Figure 14: Authorization Request with PKCE Challenge | Figure 14: Authorization Request with PKCE Challenge | |||
4.1.2. Code Verifier | 5.1.2. Code Verifier | |||
Upon receipt of the authorization code, the client sends the access | Upon receipt of the authorization code, the client sends the access | |||
token request to the token endpoint. The Token Binding Protocol | token request to the token endpoint. The Token Binding Protocol | |||
[I-D.ietf-tokbind-protocol] is negotiated on the TLS connection | [I-D.ietf-tokbind-protocol] is negotiated on the TLS connection | |||
between the client and the authorization server and the "Sec-Token- | between the client and the authorization server and the "Sec-Token- | |||
Binding" header, as defined in Token Binding over HTTP | Binding" header, as defined in Token Binding over HTTP | |||
[I-D.ietf-tokbind-https], is included in the access token request. | [I-D.ietf-tokbind-https], is included in the access token request. | |||
The authorization server extracts the Provided Token Binding ID from | The authorization server extracts the Provided Token Binding ID from | |||
the header value, hashes it with SHA-256, and compares it to the | the header value, hashes it with SHA-256, and compares it to the | |||
"code_challenge" value previously associated with the authorization | "code_challenge" value previously associated with the authorization | |||
code. If the values match, the token endpoint continues processing | code. If the values match, the token endpoint continues processing | |||
as normal (as defined by OAuth 2.0 [RFC6749]). If the values do not | as normal (as defined by OAuth 2.0 [RFC6749]). If the values do not | |||
match, an error response indicating "invalid_grant" MUST be returned. | match, an error response indicating "invalid_grant" MUST be returned. | |||
The "Sec-Token-Binding" header contains sufficient information for | The "Sec-Token-Binding" header contains sufficient information for | |||
verification of the authorization code and its association to the | verification of the authorization code and its association to the | |||
original authorization request. However, PKCE [RFC7636] requires | original authorization request. However, PKCE [RFC7636] requires | |||
skipping to change at page 15, line 20 ¶ | skipping to change at page 17, line 13 ¶ | |||
match, an error response indicating "invalid_grant" MUST be returned. | match, an error response indicating "invalid_grant" MUST be returned. | |||
The "Sec-Token-Binding" header contains sufficient information for | The "Sec-Token-Binding" header contains sufficient information for | |||
verification of the authorization code and its association to the | verification of the authorization code and its association to the | |||
original authorization request. However, PKCE [RFC7636] requires | original authorization request. However, PKCE [RFC7636] requires | |||
that a "code_verifier" parameter be sent with the access token | that a "code_verifier" parameter be sent with the access token | |||
request, so the static value "provided_tb" is used to meet that | request, so the static value "provided_tb" is used to meet that | |||
requirement and indicate that the Provided Token Binding ID is used | requirement and indicate that the Provided Token Binding ID is used | |||
for the verification. | for the verification. | |||
4.1.2.1. Example Code Verifier | 5.1.2.1. Example Code Verifier | |||
An example access token request, correlating to the authorization | An example access token request, correlating to the authorization | |||
request in the previous example, to the token endpoint over a TLS | request in the previous example, to the token endpoint over a TLS | |||
connection for which Token Binding has been negotiated would look | connection for which Token Binding has been negotiated would look | |||
like the following (with extra line breaks for display purposes | like the following (with extra line breaks for display purposes | |||
only). The base64url-encoded EKM from the TLS connection over which | only). The base64url-encoded EKM from the TLS connection over which | |||
the request was made is | the request was made is | |||
"pNVKtPuQFvylNYn000QowWrQKoeMkeX9H32hVuU71Bs". | "pNVKtPuQFvylNYn000QowWrQKoeMkeX9H32hVuU71Bs". | |||
POST /as/token.oauth2 HTTP/1.1 | POST /as/token.oauth2 HTTP/1.1 | |||
skipping to change at page 15, line 43 ¶ | skipping to change at page 17, line 36 ¶ | |||
Sec-Token-Binding: AIkAAgBBQEOO9GRFP-LM0hoWw6-2i318BsuuUum5AL8bt1sz | Sec-Token-Binding: AIkAAgBBQEOO9GRFP-LM0hoWw6-2i318BsuuUum5AL8bt1sz | |||
lr1EFfp5DMXMNW3O8WjcIXr2DKJnI4xnuGsE6GywQd9RbD0AQJDb3xyo9PBxj8M6Y | lr1EFfp5DMXMNW3O8WjcIXr2DKJnI4xnuGsE6GywQd9RbD0AQJDb3xyo9PBxj8M6Y | |||
jLt-6OaxgDkyoBoTkyrnNbLc8tJQ0JtXomKzBbj5qPtHDduXc6xz_lzvNpxSPxi42 | jLt-6OaxgDkyoBoTkyrnNbLc8tJQ0JtXomKzBbj5qPtHDduXc6xz_lzvNpxSPxi42 | |||
8m7wkAAA | 8m7wkAAA | |||
grant_type=authorization_code&code=mJAReTWKX7zI3oHUNd4o3PeNqNqxKGp6 | grant_type=authorization_code&code=mJAReTWKX7zI3oHUNd4o3PeNqNqxKGp6 | |||
&code_verifier=provided_tb&client_id=example-native-client-id | &code_verifier=provided_tb&client_id=example-native-client-id | |||
Figure 15: Token Request with PKCE Verifier | Figure 15: Token Request with PKCE Verifier | |||
4.2. Web Server Clients | 5.2. Web Server Clients | |||
This section describes a PKCE method suitable for web server clients, | This section describes a PKCE method suitable for web server clients, | |||
which cryptographically binds the authorization code to a Token | which cryptographically binds the authorization code to a Token | |||
Binding key pair on the browser. The authorization code is bound to | Binding key pair on the browser. The authorization code is bound to | |||
the Token Binding ID that the browser uses to deliver the | the Token Binding ID that the browser uses to deliver the | |||
authorization code to a web server client, which is sent to the | authorization code to a web server client, which is sent to the | |||
authorization server as the Referred Token Binding ID during the | authorization server as the Referred Token Binding ID during the | |||
authorization request. The web server client conveys the Token | authorization request. The web server client conveys the Token | |||
Binding ID to the authorization server when making the access token | Binding ID to the authorization server when making the access token | |||
request containing the authorization code. This binding ensures that | request containing the authorization code. This binding ensures that | |||
the authorization code cannot successfully be played or replayed to | the authorization code cannot successfully be played or replayed to | |||
the web server client from a different browser than the one that made | the web server client from a different browser than the one that made | |||
the authorization request. | the authorization request. | |||
4.2.1. Code Challenge | 5.2.1. Code Challenge | |||
As defined in Proof Key for Code Exchange [RFC7636], the client sends | As defined in Proof Key for Code Exchange [RFC7636], the client sends | |||
the code challenge as part of the OAuth 2.0 Authorization Request | the code challenge as part of the OAuth 2.0 Authorization Request | |||
with the two additional parameters: "code_challenge" and | with the two additional parameters: "code_challenge" and | |||
"code_challenge_method". | "code_challenge_method". | |||
The client must send the authorization request through the browser | The client must send the authorization request through the browser | |||
such that the Token Binding ID established between the browser and | such that the Token Binding ID established between the browser and | |||
itself is revealed to the authorization server's authorization | itself is revealed to the authorization server's authorization | |||
endpoint as the Referred Token Binding ID. Typically, this is done | endpoint as the Referred Token Binding ID. Typically, this is done | |||
skipping to change at page 16, line 39 ¶ | skipping to change at page 18, line 35 ¶ | |||
authorization code is to be bound to the Referred Token Binding ID | authorization code is to be bound to the Referred Token Binding ID | |||
from the Token Binding Message sent in the "Sec-Token-Binding" header | from the Token Binding Message sent in the "Sec-Token-Binding" header | |||
of the authorization request. | of the authorization request. | |||
When the authorization server issues the authorization code in the | When the authorization server issues the authorization code in the | |||
authorization response, it associates the Token Binding ID (or hash | authorization response, it associates the Token Binding ID (or hash | |||
thereof) and code challenge method with the authorization code so | thereof) and code challenge method with the authorization code so | |||
they can be verified later when the authorization code is presented | they can be verified later when the authorization code is presented | |||
in the access token request. | in the access token request. | |||
4.2.1.1. Example Code Challenge | 5.2.1.1. Example Code Challenge | |||
For example, the web server client sends the authorization request by | For example, the web server client sends the authorization request by | |||
redirecting the browser to the authorization endpoint. That HTTP | redirecting the browser to the authorization endpoint. That HTTP | |||
redirection response looks like the following (with extra line breaks | redirection response looks like the following (with extra line breaks | |||
for display purposes only). | for display purposes only). | |||
HTTP/1.1 302 Found | HTTP/1.1 302 Found | |||
Location: https://server.example.com?response_type=code | Location: https://server.example.com?response_type=code | |||
&client_id=example-web-client-id&state=P4FUFqYzs1ij3ffsYCP34d3 | &client_id=example-web-client-id&state=P4FUFqYzs1ij3ffsYCP34d3 | |||
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Eorg%2Fcb | &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Eorg%2Fcb | |||
skipping to change at page 17, line 38 ¶ | skipping to change at page 19, line 26 ¶ | |||
Host: server.example.com | Host: server.example.com | |||
Sec-Token-Binding: ARIAAgBBQB-XOPf5ePlf7ikATiAFEGOS503lPmRfkyymzdWw | Sec-Token-Binding: ARIAAgBBQB-XOPf5ePlf7ikATiAFEGOS503lPmRfkyymzdWw | |||
HCxl0njjxC3D0E_OVfBNqrIQxzIfkF7tWby2ZfyaE6XpwTsAQBYqhFX78vMOgDX_F | HCxl0njjxC3D0E_OVfBNqrIQxzIfkF7tWby2ZfyaE6XpwTsAQBYqhFX78vMOgDX_F | |||
d_b2dlHyHlMmkIz8iMVBY_reM98OUaJFz5IB7PG9nZ11j58LoG5QhmQoI9NXYktKZ | d_b2dlHyHlMmkIz8iMVBY_reM98OUaJFz5IB7PG9nZ11j58LoG5QhmQoI9NXYktKZ | |||
RXxrYAAAECAEFAdUFTnfQADkn1uDbQnvJEk6oQs38L92gv-KO-qlYadLoDIKe2h53 | RXxrYAAAECAEFAdUFTnfQADkn1uDbQnvJEk6oQs38L92gv-KO-qlYadLoDIKe2h53 | |||
hSiKwIP98iRj_unedkNkAMyg9e2mY4Gp7WwBAeDUOwaSXNz1e6gKohwN4SAZ5eNyx | hSiKwIP98iRj_unedkNkAMyg9e2mY4Gp7WwBAeDUOwaSXNz1e6gKohwN4SAZ5eNyx | |||
45Mh8VI4woL1BipLoqrJRoK6dxFkWgHRMuBROcLGUj5PiOoxybQH_Tom3gAA | 45Mh8VI4woL1BipLoqrJRoK6dxFkWgHRMuBROcLGUj5PiOoxybQH_Tom3gAA | |||
Figure 17: Authorization Request | Figure 17: Authorization Request | |||
4.2.2. Code Verifier | 5.2.2. Code Verifier | |||
The web server client receives the authorization code from the | The web server client receives the authorization code from the | |||
browser and extracts the Provided Token Binding ID from the "Sec- | browser and extracts the Provided Token Binding ID from the "Sec- | |||
Token-Binding" header of the request. The client sends the | Token-Binding" header of the request. The client sends the | |||
base64url-encoded (per Section 5 of [RFC4648] with all trailing | base64url-encoded (per Section 5 of [RFC4648] with all trailing | |||
padding ('=') characters omitted and without the inclusion of any | padding ('=') characters omitted and without the inclusion of any | |||
line breaks or whitespace) Provided Token Binding ID as the value of | line breaks or whitespace) Provided Token Binding ID as the value of | |||
the "code_verifier" parameter in the access token request to the | the "code_verifier" parameter in the access token request to the | |||
authorization server's token endpoint. The authorization server | authorization server's token endpoint. The authorization server | |||
compares the value of the "code_verifier" parameter to the Token | compares the value of the "code_verifier" parameter to the Token | |||
Binding ID value previously associated with the authorization code. | Binding ID value previously associated with the authorization code. | |||
If the values match, the token endpoint continues processing as | If the values match, the token endpoint continues processing as | |||
normal (as defined by OAuth 2.0 [RFC6749]). If the values do not | normal (as defined by OAuth 2.0 [RFC6749]). If the values do not | |||
match, an error response indicating "invalid_grant" MUST be returned. | match, an error response indicating "invalid_grant" MUST be returned. | |||
4.2.2.1. Example Code Verifier | 5.2.2.1. Example Code Verifier | |||
Continuing the example from the previous section, the authorization | Continuing the example from the previous section, the authorization | |||
server sends the code to the web server client by redirecting the | server sends the code to the web server client by redirecting the | |||
browser to the client's "redirect_uri", which results in the browser | browser to the client's "redirect_uri", which results in the browser | |||
making a request like the following (with extra line breaks for | making a request like the following (with extra line breaks for | |||
display purposes only) to the web server client over a TLS channel | display purposes only) to the web server client over a TLS channel | |||
for which Token Binding has been established. The base64url-encoded | for which Token Binding has been established. The base64url-encoded | |||
EKM from the TLS connection over which the request was made is | EKM from the TLS connection over which the request was made is | |||
"EzW60vyINbsb_tajt8ij3tV6cwy2KH-i8BdEMYXcNn0". | "EzW60vyINbsb_tajt8ij3tV6cwy2KH-i8BdEMYXcNn0". | |||
skipping to change at page 18, line 44 ¶ | skipping to change at page 20, line 33 ¶ | |||
Authorization: Basic b3JnLmV4YW1wbGUuY2xpZW50OmlldGY5OGNoaWNhZ28= | Authorization: Basic b3JnLmV4YW1wbGUuY2xpZW50OmlldGY5OGNoaWNhZ28= | |||
grant_type=authorization_code&code=jwD3oOa5cQvvLc81bwc4CMw | grant_type=authorization_code&code=jwD3oOa5cQvvLc81bwc4CMw | |||
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Eorg%2Fcb | &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Eorg%2Fcb | |||
&client_id=example-web-client-id | &client_id=example-web-client-id | |||
&code_verifier=AgBBQHVBU530AA5J9bg20J7yRJOqELN_C_doL_ijv | &code_verifier=AgBBQHVBU530AA5J9bg20J7yRJOqELN_C_doL_ijv | |||
qpWGnS6AyCntoed4UoisCD_fIkY_7p3nZDZADMoPXtpmOBqe1s | qpWGnS6AyCntoed4UoisCD_fIkY_7p3nZDZADMoPXtpmOBqe1s | |||
Figure 19: Exchange Authorization Code | Figure 19: Exchange Authorization Code | |||
5. Phasing in Token Binding and Preventing Downgrade Attacks | 6. Token Binding JWT Authorization Grants and Client Authentication | |||
Many OAuth implementations will be deployed in situations in which | The JWT Profile for OAuth 2.0 Client Authentication and Authorization | |||
not all participants support Token Binding. Any of combination of | Grants [RFC7523] defines the use of bearer JWTs as a means for | |||
the client, the authorization server, the protected resource, and the | requesting an OAuth 2.0 access token as well as for client | |||
user agent may not yet support Token Binding, in which case it will | authentication. This section describes extensions to that | |||
not work end-to-end. | specification enabling the application of Token Binding to JWT client | |||
authentication and JWT authorization grants. | ||||
It is a context-dependent deployment choice whether to allow | 6.1. JWT Format and Processing Requirements | |||
interactions to proceed in which Token Binding is not supported or | ||||
whether to treat Token Binding failures at any step as fatal errors. | ||||
Particularly in dynamic deployment environments in which End Users | ||||
have choices of clients, authorization servers, protected resources, | ||||
and/or user agents, it is RECOMMENDED that authorizations using one | ||||
or more components that do not implement Token Binding be allowed to | ||||
successfully proceed. This enables different components to be | ||||
upgraded to supporting Token Binding at different times, providing a | ||||
smooth transition path for phasing in Token Binding. However, when | ||||
Token Binding has been performed, any Token Binding key mismatches | ||||
MUST be treated as fatal errors. | ||||
If all the participants in an authorization interaction support Token | In addition the requirements set forth in Section 3 of RFC 7523 | |||
Binding and yet one or more of them does not use it, this is likely | [RFC7523], the following criteria must also be met for token bound | |||
evidence of a downgrade attack. In this case, the authorization | JWTs used as authorization grants or for client authentication. | |||
SHOULD be aborted with an error. For instance, if the protected | ||||
resource knows that the authorization server and the user agent both | ||||
support Token Binding and yet the access token received does not | ||||
contain Token Binding information, this is almost certainly a sign of | ||||
an attack. | ||||
The authorization server, client, and protected resource can | o The JWT MUST contain a "cnf" (confirmation) claim with a "tbh" | |||
determine whether the others support Token Binding using the metadata | (token binding hash) member identifying the Token Binding ID of | |||
values defined in the next section. They can determine whether the | the Provided Token Binding used by the client on the TLS | |||
user agent supports Token Binding by whether it negotiated Token | connection to the authorization server. The authorization server | |||
Binding for the TLS connection. | MUST reject any JWT that has a token binding hash confirmation | |||
that does not match the corresponding hash of the Provided Token | ||||
Binding ID from the "Sec-Token-Binding" header of the request. | ||||
6. Token Binding Metadata | 6.2. Token Bound JWTs for Client Authentication | |||
6.1. Token Binding Client Metadata | To use a token bound JWT for client authentication, the client uses | |||
the parameter values and encodings from Section 2.2 of RFC 7523 | ||||
[RFC7523] with one exception: the value of the | ||||
"client_assertion_type" is "urn:ietf:params:oauth:client-assertion- | ||||
type:jwt-token-bound". | ||||
Clients supporting Token Binding that also support the OAuth 2.0 | The "OAuth Token Endpoint Authentication Methods" registry | |||
Dynamic Client Registration Protocol [RFC7591] use these metadata | [IANA.OAuth.Parameters] contains values, each of which specify a | |||
values to declare their support for Token Binding of access tokens | method of authenticating a client to the authorization server. The | |||
and refresh tokens: | values are used to indicated supported and utilized client | |||
authentication methods in authorization server metadata, such as | ||||
[OpenID.Discovery] and [OAuth.AuthorizationMetadata], and in OAuth | ||||
2.0 Dynamic Client Registration Protocol [RFC7591]. The values | ||||
"private_key_jwt" and "client_secret_jwt" are designated by OpenID | ||||
Connect [OpenID.Core] as authentication method values for bearer JWT | ||||
client authentication using asymmetric and symmetric JWS [RFC7515] | ||||
algorithms respectively. For Token Bound JWT for client | ||||
authentication, this specification defines and registers the | ||||
following authentication method values. | ||||
client_access_token_token_binding_supported | private_key_token_bound_jwt | |||
OPTIONAL. Boolean value specifying whether the client supports | Indicates that client authentication to the authorization server | |||
Token Binding of access tokens. If omitted, the default value is | will occur with a Token Bound JWT, which is signed with a client's | |||
"false". | private key. | |||
client_refresh_token_token_binding_supported | client_secret_token_bound_jwt | |||
OPTIONAL. Boolean value specifying whether the client supports | Indicates that client authentication to the authorization server | |||
Token Binding of refresh tokens. If omitted, the default value is | will occur with a Token Bound JWT, which is integrity protected | |||
"false". | with a MAC using the octets of the UTF-8 representation of the | |||
client secret as the shared key. | ||||
6.2. Token Binding Authorization Server Metadata | Note that just as with the "private_key_jwt" and "client_secret_jwt" | |||
authentication methods, the "token_endpoint_auth_signing_alg" client | ||||
registration parameter may be used to indicate the JWS algorithm used | ||||
for signing the client authentication JWT for the authentication | ||||
methods defined above. | ||||
Authorization servers supporting Token Binding that also support | 6.3. Token Bound JWTs for as Authorization Grants | |||
OAuth 2.0 Authorization Server Metadata [OAuth.AuthorizationMetadata] | ||||
use these metadata values to declare their support for Token Binding | ||||
of access tokens and refresh tokens: | ||||
as_access_token_token_binding_supported | To use a token bound JWT for an authorization grant, the client uses | |||
OPTIONAL. Boolean value specifying whether the authorization | the parameter values and encodings from Section 2.1 of RFC 7523 | |||
server supports Token Binding of access tokens. If omitted, the | [RFC7523] with one exception: the value of the "grant_type" is | |||
default value is "false". | "urn:ietf:params:oauth:grant-type:jwt-token-bound". | |||
as_refresh_token_token_binding_supported | 7. Security Considerations | |||
OPTIONAL. Boolean value specifying whether the authorization | ||||
server supports Token Binding of refresh tokens. If omitted, the | ||||
default value is "false". | ||||
6.3. Token Binding Protected Resource Metadata | 7.1. Phasing in Token Binding | |||
Protected resources supporting Token Binding that also support the | Many OAuth implementations will be deployed in situations in which | |||
OAuth 2.0 Protected Resource Metadata [OAuth.ResourceMetadata] use | not all participants support Token Binding. Any of combination of | |||
this metadata value to declare their support for Token Binding of | the client, the authorization server, the protected resource, and the | |||
access tokens: | user agent may not yet support Token Binding, in which case it will | |||
not work end-to-end. | ||||
resource_access_token_token_binding_supported | It is a context-dependent deployment choice whether to allow | |||
OPTIONAL. Boolean value specifying whether the protected resource | interactions to proceed in which Token Binding is not supported or | |||
supports Token Binding of access tokens. If omitted, the default | whether to treat the omission of Token Binding at any step as a fatal | |||
value is "false". | error. Particularly in dynamic deployment environments in which End | |||
Users have choices of clients, authorization servers, protected | ||||
resources, and/or user agents, it is recommended that, for some | ||||
reasonable period of time during which Token Binding technology is | ||||
being adopted, authorizations using one or more components that do | ||||
not implement Token Binding be allowed to successfully proceed. This | ||||
enables different components to be upgraded to supporting Token | ||||
Binding at different times, providing a smooth transition path for | ||||
phasing in Token Binding. However, when Token Binding has been | ||||
performed, any Token Binding key mismatches MUST be treated as fatal | ||||
errors. | ||||
7. Security Considerations | In more controlled deployment environments where the participants in | |||
an authorization interaction are known or expected to support Token | ||||
Binding and yet one or more of them does not use it, the | ||||
authorization SHOULD be aborted with an error. For instance, an | ||||
authorization server should reject a token request that does not | ||||
include the "Sec-Token-Binding" header, if the request is from a | ||||
client known to support Token Binding (via configuration or the | ||||
"client_access_token_token_binding_supported" metadata parameter). | ||||
If a refresh request is received by the authorization server | 7.2. Binding of Refresh Tokens | |||
containing a Referred Token Binding ID and the refresh token in the | ||||
request is not itself token bound, then it is not clear that token | Section 6 of RFC 6749 [RFC6749] requires that a refresh token be | |||
binding the access token adds significant value. This situation | bound to the client to which it was issued and that, if the client | |||
should be considered an open issue for discussion by the working | type is confidential or the client was issued client credentials (or | |||
group. | assigned other authentication requirements), the client must | |||
authenticate with the authorization server when presenting the | ||||
refresh token. As a result, for non-public clients, refresh tokens | ||||
are indirectly bound to the client's credentials and cannot be used | ||||
without the associated client authentication. Non-public clients | ||||
then are afforded protections (equivalent to the strength of their | ||||
authentication credentials) against unauthorized replay of refresh | ||||
tokens and it is reasonable to not Token Bind refresh tokens for such | ||||
clients while still Toking Binding the issued access tokens. Refresh | ||||
tokens issued to public clients, however, do not have the benefit of | ||||
such protections and authorization servers MAY elect to disallow | ||||
public clients from registering or establishing configuration that | ||||
would allow Token Bound access tokens but unbound refresh tokens. | ||||
Some web-based confidential clients implemented as distributed nodes | ||||
may be perfectly capable of implementing access token binding (if the | ||||
access token remains on the node it was bound to, the token binding | ||||
keys would be locally available for that node to prove possession), | ||||
but may struggle with refresh token binding due to an inability to | ||||
share token binding key material between nodes. As confidential | ||||
clients already have credentials which are required to use the | ||||
refresh token, and those credentials should only ever be sent over | ||||
TLS server-to-server between the client and the Token Endpoint, there | ||||
is still value in token binding access tokens without token binding | ||||
refresh tokens. Authorization servers SHOULD consider supporting | ||||
access token binding without refresh token binding for confidential | ||||
web clients as there are still security benefits to do so. | ||||
Clients MUST declare through dynamic (Section 4.1) or static | ||||
registration information what types of token bound tokens they | ||||
support to enable the server to bind tokens accordingly, taking into | ||||
account any phase-in policies. Authorization MAY reject requests | ||||
from any client who does not support token binding (by returning an | ||||
OAuth error response) per their own security policies. | ||||
8. IANA Considerations | 8. IANA Considerations | |||
8.1. OAuth Dynamic Client Registration Metadata Registration | 8.1. OAuth Dynamic Client Registration Metadata Registration | |||
This specification registers the following client metadata | This specification registers the following client metadata | |||
definitions in the IANA "OAuth Dynamic Client Registration Metadata" | definitions in the IANA "OAuth Dynamic Client Registration Metadata" | |||
registry [IANA.OAuth.Parameters] established by [RFC7591]: | registry [IANA.OAuth.Parameters] established by [RFC7591]: | |||
8.1.1. Registry Contents | 8.1.1. Registry Contents | |||
o Client Metadata Name: | o Client Metadata Name: | |||
"client_access_token_token_binding_supported" | "client_access_token_token_binding_supported" | |||
o Client Metadata Description: Boolean value specifying whether the | o Client Metadata Description: Boolean value specifying whether the | |||
client supports Token Binding of access tokens | client supports Token Binding of access tokens | |||
o Change Controller: IESG | o Change Controller: IESG | |||
o Specification Document(s): Section 6.1 of [[ this specification ]] | o Specification Document(s): Section 4.1 of [[ this specification ]] | |||
o Client Metadata Name: | o Client Metadata Name: | |||
"client_refresh_token_token_binding_supported" | "client_refresh_token_token_binding_supported" | |||
o Client Metadata Description: Boolean value specifying whether the | o Client Metadata Description: Boolean value specifying whether the | |||
client supports Token Binding of refresh tokens | client supports Token Binding of refresh tokens | |||
o Change Controller: IESG | o Change Controller: IESG | |||
o Specification Document(s): Section 6.1 of [[ this specification ]] | o Specification Document(s): Section 4.1 of [[ this specification ]] | |||
8.2. OAuth Authorization Server Metadata Registration | 8.2. OAuth Authorization Server Metadata Registration | |||
This specification registers the following metadata definitions in | This specification registers the following metadata definitions in | |||
the IANA "OAuth Authorization Server Metadata" registry established | the IANA "OAuth Authorization Server Metadata" registry established | |||
by [OAuth.AuthorizationMetadata]: | by [OAuth.AuthorizationMetadata]: | |||
8.2.1. Registry Contents | 8.2.1. Registry Contents | |||
o Metadata Name: "as_access_token_token_binding_supported" | o Metadata Name: "as_access_token_token_binding_supported" | |||
o Metadata Description: Boolean value specifying whether the | o Metadata Description: Boolean value specifying whether the | |||
authorization server supports Token Binding of access tokens | authorization server supports Token Binding of access tokens | |||
o Change Controller: IESG | o Change Controller: IESG | |||
o Specification Document(s): Section 6.2 of [[ this specification ]] | o Specification Document(s): Section 4.2 of [[ this specification ]] | |||
o Metadata Name: "as_refresh_token_token_binding_supported" | o Metadata Name: "as_refresh_token_token_binding_supported" | |||
o Metadata Description: Boolean value specifying whether the | o Metadata Description: Boolean value specifying whether the | |||
authorization server supports Token Binding of refresh tokens | authorization server supports Token Binding of refresh tokens | |||
o Change Controller: IESG | o Change Controller: IESG | |||
o Specification Document(s): Section 6.2 of [[ this specification ]] | o Specification Document(s): Section 4.2 of [[ this specification ]] | |||
8.3. OAuth Protected Resource Metadata Registration | ||||
This specification registers the following client metadata definition | ||||
in the IANA "OAuth Protected Resource Metadata" registry established | ||||
by [OAuth.ResourceMetadata]: | ||||
8.3.1. Registry Contents | ||||
o Resource Metadata Name: | ||||
"resource_access_token_token_binding_supported" | ||||
o Resource Metadata Description: Boolean value specifying whether | ||||
the protected resource supports Token Binding of access tokens | ||||
o Change Controller: IESG | ||||
o Specification Document(s): Section 6.3 of [[ this specification ]] | ||||
8.4. PKCE Code Challenge Method Registration | 8.3. PKCE Code Challenge Method Registration | |||
This specification requests registration of the following Code | This specification requests registration of the following Code | |||
Challenge Method Parameter Names in the IANA "PKCE Code Challenge | Challenge Method Parameter Names in the IANA "PKCE Code Challenge | |||
Methods" registry [IANA.OAuth.Parameters] established by [RFC7636]. | Methods" registry [IANA.OAuth.Parameters] established by [RFC7636]. | |||
8.4.1. Registry Contents | 8.3.1. Registry Contents | |||
o Code Challenge Method Parameter Name: TB-S256 | o Code Challenge Method Parameter Name: TB-S256 | |||
o Change controller: IESG | o Change controller: IESG | |||
o Specification document(s): Section 4.1.1 of [[ this specification | o Specification document(s): Section 5.1.1 of [[ this specification | |||
]] | ]] | |||
o Code Challenge Method Parameter Name: referred_tb | o Code Challenge Method Parameter Name: referred_tb | |||
o Change controller: IESG | o Change controller: IESG | |||
o Specification document(s): Section 4.2.1 of [[ this specification | o Specification document(s): Section 5.2.1 of [[ this specification | |||
]] | ]] | |||
9. References | 9. Token Endpoint Authentication Method Registration | |||
9.1. Normative References | This specification requests registration of the following values in | |||
the IANA "OAuth Token Endpoint Authentication Methods" registry | ||||
[IANA.OAuth.Parameters] established by [RFC7591]. | ||||
9.1. Registry Contents | ||||
o Token Endpoint Authentication Method Name: | ||||
"client_secret_token_bound_jwt" | ||||
o Change Controller: IESG | ||||
o Specification Document(s): Section 6 of [[ this specification ]] | ||||
o Token Endpoint Authentication Method Name: | ||||
"private_key_token_bound_jwt" | ||||
o Change Controller: IESG | ||||
o Specification Document(s): Section 6 of [[ this specification ]] | ||||
10. Sub-Namespace Registrations | ||||
This specification requests registration of the following values in | ||||
the IANA "OAuth URI" registry [IANA.OAuth.Parameters] established in | ||||
An IETF URN Sub-Namespace for OAuth [RFC6755]. | ||||
10.1. Registry Contents | ||||
o URN: urn:ietf:params:oauth:grant-type:jwt-token-bound | ||||
o Common Name: Token Bound JWT Grant Type for OAuth 2.0 | ||||
o Change controller: IESG | ||||
o Specification Document: Section 6 of [[ this specification ]] | ||||
o URN: urn:ietf:params:oauth:client-assertion-type:jwt-token-bound | ||||
o Common Name: Token Bound JWT for OAuth 2.0 Client Authentication | ||||
o Change controller: IESG | ||||
o Specification Document: Section 6 of [[ this specification ]] | ||||
11. References | ||||
11.1. Normative References | ||||
[I-D.ietf-tokbind-https] | [I-D.ietf-tokbind-https] | |||
Popov, A., Nystrom, M., Balfanz, D., Langley, A., and J. | Popov, A., Nystrom, M., Balfanz, D., Langley, A., Harper, | |||
Hodges, "Token Binding over HTTP", draft-ietf-tokbind- | N., and J. Hodges, "Token Binding over HTTP", draft-ietf- | |||
https-08 (work in progress), February 2017. | tokbind-https-10 (work in progress), July 2017. | |||
[I-D.ietf-tokbind-negotiation] | [I-D.ietf-tokbind-negotiation] | |||
Popov, A., Nystrom, M., Balfanz, D., and A. Langley, | Popov, A., Nystrom, M., Balfanz, D., and A. Langley, | |||
"Transport Layer Security (TLS) Extension for Token | "Transport Layer Security (TLS) Extension for Token | |||
Binding Protocol Negotiation", draft-ietf-tokbind- | Binding Protocol Negotiation", draft-ietf-tokbind- | |||
negotiation-07 (work in progress), February 2017. | negotiation-10 (work in progress), October 2017. | |||
[I-D.ietf-tokbind-protocol] | [I-D.ietf-tokbind-protocol] | |||
Popov, A., Nystrom, M., Balfanz, D., Langley, A., and J. | Popov, A., Nystrom, M., Balfanz, D., Langley, A., and J. | |||
Hodges, "The Token Binding Protocol Version 1.0", draft- | Hodges, "The Token Binding Protocol Version 1.0", draft- | |||
ietf-tokbind-protocol-13 (work in progress), February | ietf-tokbind-protocol-16 (work in progress), October 2017. | |||
2017. | ||||
[IANA.OAuth.Parameters] | [IANA.OAuth.Parameters] | |||
IANA, "OAuth Parameters", | IANA, "OAuth Parameters", | |||
<http://www.iana.org/assignments/oauth-parameters>. | <http://www.iana.org/assignments/oauth-parameters>. | |||
[JWT] Jones, M., Bradley, J., and N. Sakimura, "JSON Web Token | [JWT] Jones, M., Bradley, J., and N. Sakimura, "JSON Web Token | |||
(JWT)", RFC 7519, DOI 10.17487/RFC7519, May 2015, | (JWT)", RFC 7519, DOI 10.17487/RFC7519, May 2015, | |||
<http://tools.ietf.org/html/rfc7519>. | <http://tools.ietf.org/html/rfc7519>. | |||
[OAuth.AuthorizationMetadata] | [OAuth.AuthorizationMetadata] | |||
Jones, M., Sakimura, N., and J. Bradley, "OAuth 2.0 | Jones, M., Sakimura, N., and J. Bradley, "OAuth 2.0 | |||
Authorization Server Metadata", draft-ietf-oauth- | Authorization Server Metadata", draft-ietf-oauth- | |||
discovery-06 (work in progress), March 2017, | discovery-07 (work in progress), March 2017, | |||
<http://tools.ietf.org/html/ | <http://tools.ietf.org/html/ | |||
draft-ietf-oauth-discovery-06>. | draft-ietf-oauth-discovery-07>. | |||
[OAuth.ResourceMetadata] | ||||
Jones, M. and P. Hunt, "OAuth 2.0 Protected Resource | ||||
Metadata", draft-jones-oauth-resource-metadata-01 (work in | ||||
progress), January 2017, <http://tools.ietf.org/html/ | ||||
draft-jones-oauth-resource-metadata-01>. | ||||
[OpenID.TokenBinding] | [OpenID.TokenBinding] | |||
Jones, M., Bradley, J., and B. Campbell, "OpenID Connect | Jones, M., Bradley, J., and B. Campbell, "OpenID Connect | |||
Token Bound Authentication 1.0", July 2016, | Token Bound Authentication 1.0", October 2017, | |||
<http://openid.net/specs/ | <http://openid.net/specs/ | |||
openid-connect-token-bound-authentication-1_0.html>. | openid-connect-token-bound-authentication-1_0-02.html>. | |||
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate | [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate | |||
Requirement Levels", BCP 14, RFC 2119, | Requirement Levels", BCP 14, RFC 2119, | |||
DOI 10.17487/RFC2119, March 1997, | DOI 10.17487/RFC2119, March 1997, | |||
<http://www.rfc-editor.org/info/rfc2119>. | <https://www.rfc-editor.org/info/rfc2119>. | |||
[RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data | [RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data | |||
Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006, | Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006, | |||
<http://www.rfc-editor.org/info/rfc4648>. | <https://www.rfc-editor.org/info/rfc4648>. | |||
[RFC6749] Hardt, D., Ed., "The OAuth 2.0 Authorization Framework", | [RFC6749] Hardt, D., Ed., "The OAuth 2.0 Authorization Framework", | |||
RFC 6749, DOI 10.17487/RFC6749, October 2012, | RFC 6749, DOI 10.17487/RFC6749, October 2012, | |||
<http://www.rfc-editor.org/info/rfc6749>. | <https://www.rfc-editor.org/info/rfc6749>. | |||
[RFC7230] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer | [RFC7230] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer | |||
Protocol (HTTP/1.1): Message Syntax and Routing", | Protocol (HTTP/1.1): Message Syntax and Routing", | |||
RFC 7230, DOI 10.17487/RFC7230, June 2014, | RFC 7230, DOI 10.17487/RFC7230, June 2014, | |||
<http://www.rfc-editor.org/info/rfc7230>. | <https://www.rfc-editor.org/info/rfc7230>. | |||
[RFC7523] Jones, M., Campbell, B., and C. Mortimore, "JSON Web Token | ||||
(JWT) Profile for OAuth 2.0 Client Authentication and | ||||
Authorization Grants", RFC 7523, DOI 10.17487/RFC7523, May | ||||
2015, <https://www.rfc-editor.org/info/rfc7523>. | ||||
[RFC7591] Richer, J., Ed., Jones, M., Bradley, J., Machulak, M., and | ||||
P. Hunt, "OAuth 2.0 Dynamic Client Registration Protocol", | ||||
RFC 7591, DOI 10.17487/RFC7591, July 2015, | ||||
<https://www.rfc-editor.org/info/rfc7591>. | ||||
[RFC7636] Sakimura, N., Ed., Bradley, J., and N. Agarwal, "Proof Key | [RFC7636] Sakimura, N., Ed., Bradley, J., and N. Agarwal, "Proof Key | |||
for Code Exchange by OAuth Public Clients", RFC 7636, | for Code Exchange by OAuth Public Clients", RFC 7636, | |||
DOI 10.17487/RFC7636, September 2015, | DOI 10.17487/RFC7636, September 2015, | |||
<http://www.rfc-editor.org/info/rfc7636>. | <https://www.rfc-editor.org/info/rfc7636>. | |||
[RFC7662] Richer, J., Ed., "OAuth 2.0 Token Introspection", | [RFC7662] Richer, J., Ed., "OAuth 2.0 Token Introspection", | |||
RFC 7662, DOI 10.17487/RFC7662, October 2015, | RFC 7662, DOI 10.17487/RFC7662, October 2015, | |||
<http://www.rfc-editor.org/info/rfc7662>. | <https://www.rfc-editor.org/info/rfc7662>. | |||
[RFC7800] Jones, M., Bradley, J., and H. Tschofenig, "Proof-of- | [RFC7800] Jones, M., Bradley, J., and H. Tschofenig, "Proof-of- | |||
Possession Key Semantics for JSON Web Tokens (JWTs)", | Possession Key Semantics for JSON Web Tokens (JWTs)", | |||
RFC 7800, DOI 10.17487/RFC7800, April 2016, | RFC 7800, DOI 10.17487/RFC7800, April 2016, | |||
<http://www.rfc-editor.org/info/rfc7800>. | <https://www.rfc-editor.org/info/rfc7800>. | |||
[SHS] National Institute of Standards and Technology, "Secure | [SHS] National Institute of Standards and Technology, "Secure | |||
Hash Standard (SHS)", FIPS PUB 180-4, March 2012, | Hash Standard (SHS)", FIPS PUB 180-4, March 2012, | |||
<http://csrc.nist.gov/publications/fips/fips180-4/ | <http://csrc.nist.gov/publications/fips/fips180-4/ | |||
fips-180-4.pdf>. | fips-180-4.pdf>. | |||
9.2. Informative References | 11.2. Informative References | |||
[I-D.ietf-oauth-native-apps] | [BCP212] Denniss, W. and J. Bradley, "OAuth 2.0 for Native Apps", | |||
Denniss, W. and J. Bradley, "OAuth 2.0 for Native Apps", | BCP 212, RFC 8252, DOI 10.17487/RFC8252, October 2017, | |||
draft-ietf-oauth-native-apps-08 (work in progress), March | <https://www.rfc-editor.org/info/rfc8252>. | |||
2017. | ||||
[OpenID.Core] | [OpenID.Core] | |||
Sakimura, N., Bradley, J., Jones, M., de Medeiros, B., and | Sakimura, N., Bradley, J., Jones, M., de Medeiros, B., and | |||
C. Mortimore, "OpenID Connect Core 1.0", August 2015, | C. Mortimore, "OpenID Connect Core 1.0", August 2015, | |||
<http://openid.net/specs/openid-connect-core-1_0.html>. | <http://openid.net/specs/openid-connect-core-1_0.html>. | |||
[RFC7523] Jones, M., Campbell, B., and C. Mortimore, "JSON Web Token | [OpenID.Discovery] | |||
(JWT) Profile for OAuth 2.0 Client Authentication and | Sakimura, N., Bradley, J., Jones, M., and E. Jay, "OpenID | |||
Authorization Grants", RFC 7523, DOI 10.17487/RFC7523, May | Connect Discovery 1.0", August 2015, | |||
2015, <http://www.rfc-editor.org/info/rfc7523>. | <http://openid.net/specs/ | |||
openid-connect-discovery-1_0.html>. | ||||
[RFC7591] Richer, J., Ed., Jones, M., Bradley, J., Machulak, M., and | [RFC6755] Campbell, B. and H. Tschofenig, "An IETF URN Sub-Namespace | |||
P. Hunt, "OAuth 2.0 Dynamic Client Registration Protocol", | for OAuth", RFC 6755, DOI 10.17487/RFC6755, October 2012, | |||
RFC 7591, DOI 10.17487/RFC7591, July 2015, | <https://www.rfc-editor.org/info/rfc6755>. | |||
<http://www.rfc-editor.org/info/rfc7591>. | ||||
[RFC7515] Jones, M., Bradley, J., and N. Sakimura, "JSON Web | ||||
Signature (JWS)", RFC 7515, DOI 10.17487/RFC7515, May | ||||
2015, <https://www.rfc-editor.org/info/rfc7515>. | ||||
Appendix A. Acknowledgements | Appendix A. Acknowledgements | |||
The authors would like to thank the following people for their | The authors would like to thank the following people for their | |||
contributions to the specification: Dirk Balfanz, Andrei Popov, | contributions to the specification: Dirk Balfanz, Andrei Popov, | |||
Justin Richer, and Nat Sakimura. | Justin Richer, and Nat Sakimura. | |||
Appendix B. Open Issues | Appendix B. Document History | |||
o What should we do in the case that a refresh request for a token | [[ to be removed by the RFC Editor before publication as an RFC ]] | |||
bound access token is received when the refresh token used in the | ||||
request is not token bound? | ||||
o Currently the only way to request a token bound access token is | -05 | |||
via the referred token binding. By definition the referred token | ||||
binding also comes with the provided token binding and the | ||||
provided token binding is what is used to bind the refresh token. | ||||
However, web server clients will typically be distributed/ | ||||
clustered and very likely will not want to, or be capable of, | ||||
dealing with token bound refresh tokens. Such clients will have | ||||
credentials established with the AS for authenticating to the | ||||
token endpoint and refresh tokens are already bound to the client. | ||||
So token binding the refresh tokens doesn't add much, if anything, | ||||
in this case. But accessing private token binding keys in a | ||||
distributed system will be cumbersome or even impossible. | ||||
Tracking and properly utilizing the association of a token binding | ||||
key with each individual refresh token would also be exceptionally | ||||
cumbersome (whereas client credentials are for the client and | ||||
decoupled from individual refresh tokens) but without some such | ||||
mechanism the token binding key cannot be changed without | ||||
implicitly invalidating all the bound refresh tokens the web | ||||
server client has stored for that AS. It seems necessary to | ||||
provide some mechanism for a client to opt-out of having refresh | ||||
tokens token bound while still allowing for token binding of | ||||
access tokens. | ||||
o Should the scope of this document include standardization or | o State that authorization servers should not token bind refresh | |||
guidance on token binding of JWT Client Authentication and/or | tokens issued to a client that doesn't support bound refresh | |||
Authorization Grants from RFC 7523? | tokens, which can be indicated by the | |||
"client_refresh_token_token_binding_supported" client metadata | ||||
parameter. | ||||
o The Metadata (Section 6) and what can and cannot be reliably | o Add Token Binding for JWT Authorization Grants and JWT Client | |||
inferred from it (Section 5) need additional evaluation and work. | Authentication. | |||
OAuth 2.0 Protected Resource Metadata [OAuth.ResourceMetadata] is | ||||
no longer a going concern, but is currently referenced herein. | ||||
Boolean values do not adequately convey Token Binding support, as | ||||
different components may support different key parameters types. | ||||
And successful negotiation likely doesn't provide the application | ||||
layer info about all the supported key parameters types but rather | ||||
just the one that was negotiated. | ||||
Appendix C. Document History | o Adjust the language around aborting authorizations in Phasing in | |||
Token Binding to be somewhat more general and not only about | ||||
downgrades. | ||||
[[ to be removed by the RFC Editor before publication as an RFC ]] | o Remove reference to, and usage of, 'OAuth 2.0 Protected Resource | |||
Metadata', which is no longer a going concern. | ||||
o Moved "Token Binding Metadata" section before "Token Binding for | ||||
Authorization Codes" to be closer to the "Token Binding for Access | ||||
Tokens" and "Token Binding for Refresh Tokens", to which it is | ||||
more closely related. | ||||
o Update references for draft-ietf-tokbind- negotiation(-10), | ||||
protocol(-16), and https(-10), as well as draft-ietf-oauth- | ||||
discovery(-07), and BCP212/RFC8252 OAuth 2.0 for Native Apps. | ||||
-04 | -04 | |||
o Define how to convey token binding information of an access token | o Define how to convey token binding information of an access token | |||
via RFC 7662 OAuth 2.0 Token Introspection (note that the | via RFC 7662 OAuth 2.0 Token Introspection (note that the | |||
Introspection Response Registration request for cnf/Confirmation | Introspection Response Registration request for cnf/Confirmation | |||
is in https://tools.ietf.org/html/draft-ietf-oauth-mtls- | is in https://tools.ietf.org/html/draft-ietf-oauth-mtls- | |||
02#section-4.3 which will likely be published and registered prior | 02#section-4.3 which will likely be published and registered prior | |||
to this document). | to this document). | |||
skipping to change at page 27, line 15 ¶ | skipping to change at page 30, line 13 ¶ | |||
token-binding-00. | token-binding-00. | |||
Authors' Addresses | Authors' Addresses | |||
Michael B. Jones | Michael B. Jones | |||
Microsoft | Microsoft | |||
Email: mbj@microsoft.com | Email: mbj@microsoft.com | |||
URI: http://self-issued.info/ | URI: http://self-issued.info/ | |||
John Bradley | ||||
Ping Identity | ||||
Email: ve7jtb@ve7jtb.com | ||||
URI: http://www.thread-safe.com/ | ||||
Brian Campbell | Brian Campbell | |||
Ping Identity | Ping Identity | |||
Email: brian.d.campbell@gmail.com | Email: brian.d.campbell@gmail.com | |||
URI: https://twitter.com/__b_c | ||||
John Bradley | ||||
Yubico | ||||
Email: ve7jtb@ve7jtb.com | ||||
URI: http://www.thread-safe.com/ | ||||
William Denniss | William Denniss | |||
1600 Amphitheatre Pkwy | 1600 Amphitheatre Pkwy | |||
Mountain View, CA 94043 | Mountain View, CA 94043 | |||
USA | USA | |||
Email: wdenniss@google.com | Email: wdenniss@google.com | |||
URI: http://wdenniss.com/ | URI: http://wdenniss.com/ | |||
End of changes. 81 change blocks. | ||||
257 lines changed or deleted | 363 lines changed or added | |||
This html diff was produced by rfcdiff 1.46. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ |