Skip to content

Commit 770b177

Browse files
committed
fix: recognize N_A in the token exchange grant
1 parent 2af5eb8 commit 770b177

File tree

4 files changed

+140
-9
lines changed

4 files changed

+140
-9
lines changed

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@
8686
},
8787
"dependencies": {
8888
"jose": "^6.0.12",
89-
"oauth4webapi": "^3.6.1"
89+
"oauth4webapi": "^3.7.0"
9090
},
9191
"devDependencies": {
9292
"@koa/cors": "^5.0.0",

src/index.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4199,11 +4199,17 @@ export async function genericGrantRequest(
41994199
signal: signal(timeout),
42004200
},
42014201
)
4202-
.then((response) =>
4203-
oauth.processGenericTokenEndpointResponse(as, c, response, {
4202+
.then((response) => {
4203+
let recognizedTokenTypes: oauth.RecognizedTokenTypes | undefined
4204+
if (grantType === 'urn:ietf:params:oauth:grant-type:token-exchange') {
4205+
recognizedTokenTypes = { n_a: () => {} }
4206+
}
4207+
4208+
return oauth.processGenericTokenEndpointResponse(as, c, response, {
42044209
[oauth.jweDecrypt]: decrypt,
4205-
}),
4206-
)
4210+
recognizedTokenTypes,
4211+
})
4212+
})
42074213
.catch(errorHandler)
42084214

42094215
addHelpers(result)

test/n_a.test.ts

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import test from 'ava'
2+
import * as client from '../src/index.js'
3+
import * as undici from 'undici'
4+
5+
test('genericGrantRequest accepts n_a token type in token exchange grant response', async (t) => {
6+
let agent = new undici.MockAgent()
7+
agent.disableNetConnect()
8+
9+
const mockAgent = agent.get('https://as.example.com')
10+
11+
// Mock the token endpoint to return a response with n_a token type
12+
mockAgent
13+
.intercept({
14+
method: 'POST',
15+
path: '/token',
16+
})
17+
.reply(
18+
200,
19+
{
20+
access_token: 'test-access-token',
21+
token_type: 'n_a',
22+
expires_in: 3600,
23+
issued_token_type: 'urn:ietf:params:oauth:token-type:access_token',
24+
},
25+
{
26+
headers: {
27+
'content-type': 'application/json',
28+
},
29+
},
30+
)
31+
32+
const config = new client.Configuration(
33+
{
34+
issuer: 'https://as.example.com',
35+
token_endpoint: 'https://as.example.com/token',
36+
},
37+
'test-client-id',
38+
undefined,
39+
client.None(),
40+
)
41+
42+
client.allowInsecureRequests(config)
43+
// @ts-ignore
44+
config[client.customFetch] = (url, options) => {
45+
return undici.fetch(url, { ...options, dispatcher: agent })
46+
}
47+
48+
const result = await client.genericGrantRequest(
49+
config,
50+
'urn:ietf:params:oauth:grant-type:token-exchange',
51+
{
52+
subject_token: 'subject-token-value',
53+
subject_token_type: 'urn:ietf:params:oauth:token-type:access_token',
54+
},
55+
)
56+
57+
t.is(result.access_token, 'test-access-token')
58+
t.is(result.token_type, 'n_a')
59+
t.is(result.expires_in, 3600)
60+
t.is(
61+
result.issued_token_type,
62+
'urn:ietf:params:oauth:token-type:access_token',
63+
)
64+
65+
t.notThrows(() => agent.assertNoPendingInterceptors())
66+
})
67+
68+
test('genericGrantRequest with other grant types does not add n_a token type recognition', async (t) => {
69+
let agent = new undici.MockAgent()
70+
agent.disableNetConnect()
71+
72+
const mockAgent = agent.get('https://as.example.com')
73+
74+
mockAgent
75+
.intercept({
76+
method: 'POST',
77+
path: '/token',
78+
})
79+
.reply(
80+
200,
81+
{
82+
access_token: 'test-access-token',
83+
token_type: 'n_a',
84+
expires_in: 3600,
85+
},
86+
{
87+
headers: {
88+
'content-type': 'application/json',
89+
},
90+
},
91+
)
92+
93+
const config = new client.Configuration(
94+
{
95+
issuer: 'https://as.example.com',
96+
token_endpoint: 'https://as.example.com/token',
97+
},
98+
'test-client-id',
99+
undefined,
100+
client.None(),
101+
)
102+
103+
client.allowInsecureRequests(config)
104+
// @ts-ignore
105+
config[client.customFetch] = (url, options) => {
106+
return undici.fetch(url, { ...options, dispatcher: agent })
107+
}
108+
109+
// This should throw because n_a token type is not recognized for JWT bearer grants
110+
await t.throwsAsync(
111+
client.genericGrantRequest(
112+
config,
113+
'urn:ietf:params:oauth:grant-type:jwt-bearer',
114+
{
115+
assertion: 'jwt-assertion-value',
116+
scope: 'test-scope',
117+
},
118+
),
119+
{
120+
message: /unsupported operation/,
121+
},
122+
)
123+
124+
t.notThrows(() => agent.assertNoPendingInterceptors())
125+
})

0 commit comments

Comments
 (0)