Skip to content

Commit 9d0cf87

Browse files
committed
docs: add RFC8693 to documentation site
1 parent c8de704 commit 9d0cf87

File tree

3 files changed

+92
-2
lines changed

3 files changed

+92
-2
lines changed

docs/.vitepress/config.ts

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export default defineConfig({
4242
{ text: "Refresh Token", link: "/grants/refresh_token" },
4343
{ text: "Password", link: "/grants/password" },
4444
{ text: "Implicit", link: "/grants/implicit" },
45+
{ text: "Token Exchange (RFC 8693)", link: "/grants/token_exchange" },
4546
],
4647
},
4748
{

docs/grants/token_exchange.md

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Token Exchange Grant
2+
3+
The [RFC 8693 - OAuth 2.0 Token Exchange](https://datatracker.ietf.org/doc/html/rfc8693) facilitates the secure exchange of tokens for accessing different resources or services. This documentation guides you through enabling this grant type on your authorization server, detailing request and response handling to ensure robust and secure token management.
4+
5+
### Enable Grant
6+
7+
To enable the token exchange grant, you'll need to provide your own implementation of `processTokenExchangeFn`. This function should orchestrate the exchange with the required third-party services based on your specific needs.
8+
9+
```ts
10+
authorizationServer.enableGrant({
11+
grant_type: "urn:ietf:params:oauth:grant-type:token-exchange",
12+
processTokenExchangeFn: async (args: ProcessTokenExchangeArgs): Promise<OAuthUser | undefined> => {
13+
const {
14+
resource,
15+
audience,
16+
scopes,
17+
requestedTokenType,
18+
subjectToken,
19+
subjectTokenType,
20+
actorToken,
21+
actorTokenType,
22+
} = args;
23+
24+
// Implement the logic to handle the token exchange.
25+
// This could involve validating the subject token, interacting with third-party services,
26+
// and generating or retrieving an appropriate access token for the user.
27+
// Example:
28+
const user = await exchangeTokenForUser(subjectToken, subjectTokenType);
29+
30+
// Return the user object associated with the exchanged token, or undefined if exchange fails
31+
return user;
32+
},
33+
})
34+
```
35+
36+
### Flow
37+
38+
The client sends a **POST** to the `/token` endpoint with the following body:
39+
40+
- **grant_type** must be set to `urn:ietf:params:oauth:grant-type:token-exchange`
41+
- **client_id** is the client identifier you received when you first created the application
42+
- **subject_token** a security token that represents the identity of the party on behalf of whom the request is being made
43+
- **subject_token_type** an identifier, as described in Section 3, that indicates the type of the security token in the subject_token parameter [See more info](https://datatracker.ietf.org/doc/html/rfc8693#TokenTypeIdentifiers)
44+
- **actor_token** (_optional_) a security token that represents the identity of the acting party
45+
- **actor_token_type** (_optional but required when actor_token is present_) an identifier that indicates the type of the security token in the actor_token parameter [See more info](https://datatracker.ietf.org/doc/html/rfc8693#TokenTypeIdentifiers)
46+
- **resource** (_optional_) a URI that indicates the target service or resource where the client intends to use the requested security token.
47+
- **audience** (_optional_) is the logical name of the target service where the client intends to use the requested security token.
48+
- **requested_token_type** (_optional_) is an identifier for the type of the requested security token [See more info](https://datatracker.ietf.org/doc/html/rfc8693#TokenTypeIdentifiers)
49+
- **scope** (_optional_) is a string with a space delimited list of requested scopes. The requested scopes must be valid for the client.
50+
51+
::: details View sample request
52+
_Did you know?_ You can authenticate by passing the `client_id` and `client_secret` as a query string, or through basic auth.
53+
54+
```http request [Query String]
55+
POST /token HTTP/1.1
56+
Host: example.com
57+
Content-Type: application/x-www-form-urlencoded
58+
59+
grant_type=urn:ietf:params:oauth:grant-type:token-exchange
60+
&client_id=ec6875c5-407a-4242-947a-1ab5e6ad632f
61+
&requested_token_type=urn:ietf:params:oauth:token-type:access_token
62+
&subject_token={steam_session_id}
63+
&subject_token_type=urn:ietf:oauth:token-type:steam_session_ticket
64+
&scope="contacts.read contacts.write"
65+
```
66+
:::
67+
68+
The authorization server will respond with the following response.
69+
70+
- **token_type** will always be `Bearer`
71+
- **expires_in** is the time the token will live in seconds
72+
- **access_token** is a JWT signed token and can be used to authenticate into the resource server
73+
- **scope** is a space delimited list of scopes the token has access to
74+
75+
::: details View sample response
76+
```http request
77+
HTTP/1.1 200 OK
78+
Content-Type: application/json; charset=UTF-8
79+
Cache-Control: no-store
80+
Pragma: no-cache
81+
82+
{
83+
token_type: 'Bearer',
84+
expires_in: 3600,
85+
access_token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDE3MDY0NjYsIm5iZiI6MTYwMTcwMjg2NiwiaWF0IjoxNjAxNzAyODY2LCJqdGkiOiJuZXcgdG9rZW4iLCJjaWQiOiJ0ZXN0IGNsaWVudCIsInNjb3BlIjoiIn0.KcXoCP6u9uhvtOoistLBskESA0tyT2I1SDe5Yn9iM4I',
86+
scope: 'contacts.create contacts.read'
87+
}
88+
```
89+
:::

src/grants/token_exchange.grant.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ export class TokenExchangeGrant extends AbstractGrant {
4343

4444
const subjectToken = this.getRequestParameter("subject_token", req);
4545

46-
const subjectTokenType = this.getRequestParameter("subject_token_type", req);
47-
4846
if (typeof subjectToken !== "string") {
4947
throw OAuthException.badRequest("subject_token is required");
5048
}
5149

50+
const subjectTokenType = this.getRequestParameter("subject_token_type", req);
51+
5252
if (!this.isSubjectTokenType(subjectTokenType)) {
5353
// https://datatracker.ietf.org/doc/html/rfc8693#section-3
5454
throw OAuthException.badRequest(`subject_token_type is required in format ${this.SUBJECT_TOKEN_TYPE_REGEX}`);

0 commit comments

Comments
 (0)