Skip to content

Commit 2c3066e

Browse files
authored
Improve OAuth2 scopes handling in OpenAPI (#3775)
1 parent 55c0b03 commit 2c3066e

File tree

4 files changed

+45
-27
lines changed

4 files changed

+45
-27
lines changed

.changeset/sunny-cobras-feel.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@gitbook/react-openapi': patch
3+
'gitbook': patch
4+
---
5+
6+
Improve OAuth2 scopes handling in OpenAPI

packages/gitbook/src/components/DocumentView/OpenAPI/style.css

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
.openapi-deprecated,
3636
.openapi-stability {
37-
@apply py-0.5 px-1.5 min-w-[1.625rem] font-normal w-fit justify-center items-center ring-1 ring-inset ring-tint bg-tint rounded text-sm leading-[calc(max(1.20em,1.25rem))] before:content-none! after:!content-none;
37+
@apply py-0.5 px-1.5 min-w-[1.625rem] font-normal w-fit justify-center items-center ring-1 ring-inset ring-tint bg-tint rounded straight-corners:rounded-none circular-corners:rounded-sm text-sm leading-[calc(max(1.20em,1.25rem))] before:content-none! after:!content-none;
3838
}
3939

4040
.openapi-stability-alpha {
@@ -72,7 +72,7 @@
7272
}
7373

7474
.openapi-markdown code {
75-
@apply py-px px-1 min-w-[1.625rem] font-normal w-fit justify-center items-center ring-1 ring-inset ring-tint bg-tint rounded text-sm leading-[calc(max(1.20em,1.25rem))] before:content-none! after:!content-none;
75+
@apply py-px px-1 min-w-[1.625rem] font-normal w-fit justify-center items-center ring-1 ring-inset ring-tint bg-tint rounded straight-corners:rounded-none circular-corners:rounded-md text-sm leading-[calc(max(1.20em,1.25rem))] before:content-none! after:!content-none;
7676
}
7777

7878
.openapi-markdown pre code {
@@ -95,7 +95,7 @@
9595
/* Method Tags */
9696
.openapi-method,
9797
.openapi-statuscode {
98-
@apply rounded uppercase font-mono items-center shrink-0 font-semibold text-[0.813rem] px-1 py-0.5 mr-2 text-tint-12/8 leading-tight align-middle inline-flex ring-1 ring-inset ring-tint-12/1 dark:ring-tint-1/1 whitespace-nowrap;
98+
@apply rounded straight-corners:rounded-none circular-corners:rounded-md uppercase font-mono items-center shrink-0 font-semibold text-[0.813rem] px-1 py-0.5 mr-2 text-tint-12/8 leading-tight align-middle inline-flex ring-1 ring-inset ring-tint-12/1 dark:ring-tint-1/1 whitespace-nowrap;
9999
}
100100

101101
.openapi-method-get,
@@ -270,11 +270,11 @@
270270
}
271271

272272
.openapi-schema-enum-value:first-child {
273-
@apply rounded-l ml-0;
273+
@apply rounded-l straight-corners:rounded-none circular-corners:rounded-l-md ml-0;
274274
}
275275

276276
.openapi-schema-enum-value:last-child {
277-
@apply rounded-r;
277+
@apply rounded-r straight-corners:rounded-none circular-corners:rounded-r-md;
278278
}
279279

280280
/* Schema Description */
@@ -308,7 +308,7 @@
308308
.openapi-schema-pattern code,
309309
.openapi-schema-enum-value code,
310310
.openapi-schema-default code {
311-
@apply py-px px-1 min-w-[1.625rem] text-tint-strong font-normal w-fit justify-center items-center ring-1 ring-inset ring-tint-subtle bg-tint rounded text-xs leading-[calc(max(1.20em,1.25rem))] before:content-none! after:!content-none;
311+
@apply py-px px-1 min-w-[1.625rem] text-tint-strong font-normal w-fit justify-center items-center ring-1 ring-inset ring-tint-subtle bg-tint rounded straight-corners:rounded-none circular-corners:rounded-md text-xs leading-[calc(max(1.20em,1.25rem))] before:content-none! after:!content-none;
312312
}
313313

314314
/* Authentication */
@@ -325,6 +325,10 @@
325325
@apply prose *:!prose-sm *:text-tint;
326326
}
327327

328+
.openapi-securities-oauth-content {
329+
@apply flex flex-col gap-1 mt-1;
330+
}
331+
328332
.openapi-securities-oauth-content.openapi-markdown code {
329333
@apply text-xs;
330334
}
@@ -334,7 +338,7 @@
334338
}
335339

336340
.openapi-securities-url {
337-
@apply ml-0.5 px-0.5 rounded hover:bg-tint transition-colors;
341+
@apply ml-0.5 px-0.5 rounded straight-corners:rounded-none circular-corners:rounded-md hover:bg-tint dark:hover:bg-tint-hover transition-colors;
338342
}
339343

340344
.openapi-securities-body {
@@ -478,7 +482,7 @@
478482
}
479483

480484
.openapi-path-variable {
481-
@apply p-px min-w-[1.625rem] text-tint-strong font-normal w-fit justify-center items-center ring-1 ring-inset ring-tint bg-tint rounded text-sm leading-none before:content-none! after:!content-none;
485+
@apply p-px min-w-[1.625rem] text-tint-strong font-normal w-fit justify-center items-center ring-1 ring-inset ring-tint bg-tint rounded straight-corners:rounded-none circular-corners:rounded-md text-sm leading-none before:content-none! after:!content-none;
482486
}
483487

484488
.openapi-path-server {
@@ -601,8 +605,8 @@ body:has(.openapi-select-popover) {
601605
}
602606

603607
.openapi-select > button {
604-
@apply flex items-center font-normal cursor-pointer *:truncate gap-1.5 p-1.5 border border-tint-subtle text-tint-strong rounded leading-none;
605-
@apply hover:bg-tint-hover transition-all;
608+
@apply flex items-center font-normal cursor-pointer *:truncate gap-1.5 p-1.5 border border-tint-subtle text-tint-strong rounded straight-corners:rounded-none circular-corners:rounded-md leading-none;
609+
@apply hover:bg-tint dark:hover:bg-tint-hover transition-all;
606610
}
607611

608612
.openapi-select:not(.openapi-select-unstyled) > button {
@@ -634,7 +638,7 @@ body:has(.openapi-select-popover) {
634638
}
635639

636640
.openapi-select-popover {
637-
@apply min-w-32 z-10 max-w-[max(20rem,var(--trigger-width))] overflow-x-hidden max-h-52 overflow-y-auto p-1.5 border border-tint-subtle bg-tint-base backdrop-blur-xl rounded-md circular-corners:rounded-xl straight-corners:rounded-none;
641+
@apply min-w-32 z-10 max-w-[max(20rem,var(--trigger-width))] overflow-x-hidden max-h-52 overflow-y-auto p-1.5 border border-tint-subtle bg-tint-base backdrop-blur-xl rounded-md straight-corners:rounded-none circular-corners:rounded-xl;
638642
@apply shadow-md shadow-tint-12/1 dark:shadow-tint-1/1;
639643
}
640644

@@ -647,7 +651,7 @@ body:has(.openapi-select-popover) {
647651
}
648652

649653
.openapi-select-item {
650-
@apply text-sm flex items-center cursor-pointer px-1.5 overflow-hidden py-1 text-tint ring-0 border-none rounded !outline-none;
654+
@apply text-sm flex items-center cursor-pointer px-1.5 overflow-hidden py-1 text-tint ring-0 border-none rounded straight-corners:rounded-none circular-corners:rounded-md !outline-none;
651655
@apply hover:bg-tint-hover hover:theme-gradient:bg-tint-12/1 hover:text-tint-strong contrast-more:hover:ring-1 contrast-more:hover:ring-inset contrast-more:hover:ring-current;
652656
}
653657

@@ -743,7 +747,7 @@ body:has(.openapi-select-popover) {
743747
}
744748

745749
.openapi-tabs-tab {
746-
@apply hover:bg-primary-hover whitespace-nowrap font-mono font-normal tabular-nums hover:text-primary cursor-pointer transition-all relative text-[0.813rem] text-tint px-1 border border-transparent rounded;
750+
@apply hover:bg-primary-hover whitespace-nowrap font-mono font-normal tabular-nums hover:text-primary cursor-pointer transition-all relative text-[0.813rem] text-tint px-1 border border-transparent rounded straight-corners:rounded-none circular-corners:rounded-md;
747751
}
748752

749753
.openapi-tabs-tab[aria-selected="true"] {
@@ -814,12 +818,12 @@ body:has(.openapi-select-popover) {
814818
}
815819

816820
.openapi-schemas-disclosure > .openapi-disclosure-trigger {
817-
@apply flex items-center font-mono transition-all font-normal text-tint-strong !text-sm hover:bg-tint-subtle relative flex-1 gap-2.5 p-5 truncate -outline-offset-1;
821+
@apply flex items-center font-mono transition-all font-normal text-tint-strong !text-sm hover:bg-tint-subtle dark:hover:bg-tint-hover relative flex-1 gap-2.5 p-5 truncate -outline-offset-1;
818822
}
819823

820824
.openapi-schemas-disclosure > .openapi-disclosure-trigger,
821825
.openapi-schemas-disclosure .openapi-disclosure-panel {
822-
@apply straight-corners:!rounded-none;
826+
@apply straight-corners:!rounded-none circular-corners:!rounded-md;
823827
}
824828

825829
.openapi-disclosure-panel {
@@ -847,7 +851,7 @@ body:has(.openapi-select-popover) {
847851
.openapi-schema-alternatives .openapi-disclosure,
848852
.openapi-schemas-disclosure .openapi-schema.openapi-disclosure
849853
) {
850-
@apply rounded-xl;
854+
@apply rounded-xl straight-corners:rounded-none;
851855
}
852856

853857
.openapi-disclosure .openapi-schemas-disclosure .openapi-schema.openapi-disclosure {
@@ -997,8 +1001,8 @@ body:has(.openapi-select-popover) {
9971001
}
9981002

9991003
.openapi-path-copy-button {
1000-
@apply p-1 flex rounded-md;
1001-
@apply hover:bg-tint;
1004+
@apply p-1 flex rounded-md straight-corners:rounded-none;
1005+
@apply hover:bg-tint dark:hover:bg-tint-hover;
10021006
}
10031007

10041008
.openapi-path-copy-button-icon {

packages/react-openapi/src/OpenAPISecurities.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ function getLabelForType(security: OpenAPICustomSecurityScheme, context: OpenAPI
138138

139139
function OpenAPISchemaOAuth2Flows(props: {
140140
context: OpenAPIClientContext;
141-
security: OpenAPIV3.OAuth2SecurityScheme & { required?: boolean };
141+
security: OpenAPICustomSecurityScheme & { flows?: OpenAPIV3.OAuth2SecurityScheme['flows'] };
142142
}) {
143143
const { context, security } = props;
144144

@@ -167,15 +167,16 @@ function OpenAPISchemaOAuth2Item(props: {
167167
>];
168168
name: string;
169169
context: OpenAPIClientContext;
170-
security: OpenAPIV3.OAuth2SecurityScheme & { required?: boolean };
170+
security: OpenAPICustomSecurityScheme & { flows?: OpenAPIV3.OAuth2SecurityScheme['flows'] };
171171
}) {
172172
const { flow, context, security, name } = props;
173173

174174
if (!flow) {
175175
return null;
176176
}
177177

178-
const scopes = flow.scopes ? Object.entries(flow.scopes) : [];
178+
// If the security scheme has scopes, we don't need to display the scopes from the flow
179+
const scopes = !security.scopes?.length && flow.scopes ? Object.entries(flow.scopes) : [];
179180

180181
return (
181182
<div>

packages/react-openapi/src/resolveOpenAPIOperation.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -158,15 +158,22 @@ function resolveSecurityScopes({
158158
securityScheme?: OpenAPIV3.ReferenceObject | OpenAPIV3.SecuritySchemeObject;
159159
operationScopes?: string[];
160160
}): OpenAPISecurityScope[] | null {
161-
if (
162-
!securityScheme ||
163-
checkIsReference(securityScheme) ||
164-
isOAuthSecurityScheme(securityScheme)
165-
) {
161+
if (!operationScopes?.length || !securityScheme || checkIsReference(securityScheme)) {
166162
return null;
167163
}
168164

169-
return operationScopes?.map((scope) => [scope, undefined]) || [];
165+
// If the security scheme is an OAuth or OpenID Connect security scheme, we first check if the operation scopes are defined in the security scheme
166+
if (isOAuthSecurityScheme(securityScheme)) {
167+
const flows = securityScheme.flows ? Object.entries(securityScheme.flows) : [];
168+
169+
return flows.flatMap(([_, flow]) => {
170+
return Object.entries(flow.scopes ?? {}).filter(([scope]) =>
171+
operationScopes.includes(scope)
172+
);
173+
});
174+
}
175+
176+
return operationScopes.map((scope) => [scope, undefined]);
170177
}
171178

172179
/**

0 commit comments

Comments
 (0)