1
- from typing import Dict , Sequence
1
+ # ruff: noqa: E501
2
+ from typing import Dict , Optional , Sequence
2
3
3
4
from pydantic import BaseModel , Field
4
5
7
8
8
9
# Based on https://swagger.io/docs/open-source-tools/swagger-ui/usage/oauth2/
9
10
class OAuth2Config (BaseModel ):
11
+ """
12
+ OAuth2 configuration for Swagger UI
13
+ """
14
+
15
+ # The client ID for the OAuth2 application
10
16
clientId : str = Field (alias = "client_id" )
11
- realm : str
17
+
18
+ # The realm in which the OAuth2 application is registered. Optional.
19
+ realm : Optional [str ]
20
+
21
+ # The name of the OAuth2 application
12
22
appName : str = Field (alias = "app_name" )
23
+
24
+ # The scopes that the OAuth2 application requires. Defaults to an empty list.
13
25
scopes : Sequence [str ] = Field (default = [])
26
+
27
+ # Additional query string parameters to be included in the OAuth2 request. Defaults to an empty dictionary.
14
28
additionalQueryStringParams : Dict [str , str ] = Field (alias = "additional_query_string_params" , default = {})
29
+
30
+ # Whether to use basic authentication with the access code grant type. Defaults to False.
15
31
useBasicAuthenticationWithAccessCodeGrant : bool = Field (
16
32
alias = "use_basic_authentication_with_access_code_grant" ,
17
33
default = False ,
18
34
)
35
+
36
+ # Whether to use PKCE with the authorization code grant type. Defaults to False.
19
37
usePkceWithAuthorizationCodeGrant : bool = Field (alias = "use_pkce_with_authorization_code_grant" , default = False )
20
38
21
39
if PYDANTIC_V2 :
@@ -25,3 +43,100 @@ class OAuth2Config(BaseModel):
25
43
class Config :
26
44
extra = "allow"
27
45
allow_population_by_field_name = True
46
+
47
+
48
+ class OAuth2UnsafeConfig (OAuth2Config ):
49
+ """
50
+ This class extends the OAuth2Config class and includes the client secret.
51
+ This class NEVER BE USED IN PRODUCTION as it will expose sensitive information.
52
+ """
53
+
54
+ # The client secret for the OAuth2 application. This is sensitive information.
55
+ clientSecret : str = Field (alias = "client_secret" )
56
+
57
+
58
+ def generate_oauth2_redirect_html () -> str :
59
+ """
60
+ Generates the HTML content for the OAuth2 redirect page.
61
+ """
62
+ return """
63
+ <!doctype html>
64
+ <html lang="en-US">
65
+ <head>
66
+ <title>Swagger UI: OAuth2 Redirect</title>
67
+ </head>
68
+ <body>
69
+ <script>
70
+ 'use strict';
71
+ function run () {
72
+ var oauth2 = window.opener.swaggerUIRedirectOauth2;
73
+ var sentState = oauth2.state;
74
+ var redirectUrl = oauth2.redirectUrl;
75
+ var isValid, qp, arr;
76
+
77
+ if (/code|token|error/.test(window.location.hash)) {
78
+ qp = window.location.hash.substring(1).replace('?', '&');
79
+ } else {
80
+ qp = location.search.substring(1);
81
+ }
82
+
83
+ arr = qp.split("&");
84
+ arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';});
85
+ qp = qp ? JSON.parse('{' + arr.join() + '}',
86
+ function (key, value) {
87
+ return key === "" ? value : decodeURIComponent(value);
88
+ }
89
+ ) : {};
90
+
91
+ isValid = qp.state === sentState;
92
+
93
+ if ((
94
+ oauth2.auth.schema.get("flow") === "accessCode" ||
95
+ oauth2.auth.schema.get("flow") === "authorizationCode" ||
96
+ oauth2.auth.schema.get("flow") === "authorization_code"
97
+ ) && !oauth2.auth.code) {
98
+ if (!isValid) {
99
+ oauth2.errCb({
100
+ authId: oauth2.auth.name,
101
+ source: "auth",
102
+ level: "warning",
103
+ message: "Authorization may be unsafe, passed state was changed in server. The passed state wasn't returned from auth server."
104
+ });
105
+ }
106
+
107
+ if (qp.code) {
108
+ delete oauth2.state;
109
+ oauth2.auth.code = qp.code;
110
+ oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
111
+ } else {
112
+ let oauthErrorMsg;
113
+ if (qp.error) {
114
+ oauthErrorMsg = "["+qp.error+"]: " +
115
+ (qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
116
+ (qp.error_uri ? "More info: "+qp.error_uri : "");
117
+ }
118
+
119
+ oauth2.errCb({
120
+ authId: oauth2.auth.name,
121
+ source: "auth",
122
+ level: "error",
123
+ message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server."
124
+ });
125
+ }
126
+ } else {
127
+ oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
128
+ }
129
+ window.close();
130
+ }
131
+
132
+ if (document.readyState !== 'loading') {
133
+ run();
134
+ } else {
135
+ document.addEventListener('DOMContentLoaded', function () {
136
+ run();
137
+ });
138
+ }
139
+ </script>
140
+ </body>
141
+ </html>
142
+ """ .strip ()
0 commit comments