Add Bearer authentication support to Python client (#1999)

* add bearer auth support to python

* add bearer auth support to python

* update python oas2 petstore samples

* update samples

* add bearer format

* update php symfony samle
This commit is contained in:
William Cheng
2019-01-30 22:16:53 +08:00
committed by GitHub
parent 77d2de4e3d
commit 2eb99f602a
37 changed files with 294 additions and 89 deletions

View File

@@ -29,6 +29,7 @@ public class CodegenSecurity {
public Boolean hasMore, isBasic, isOAuth, isApiKey;
// is Basic is true for all http authentication type. Those are to differentiate basic and bearer authentication
public Boolean isBasicBasic, isBasicBearer;
public String bearerFormat;
public Map<String, Object> vendorExtensions = new HashMap<String, Object>();
// ApiKey specific
public String keyParamName;
@@ -58,6 +59,12 @@ public class CodegenSecurity {
return false;
if (isBasic != null ? !isBasic.equals(that.isBasic) : that.isBasic != null)
return false;
if (isBasicBasic != null ? !isBasicBasic.equals(that.isBasicBasic) : that.isBasicBasic != null)
return false;
if (isBasicBearer != null ? !isBasicBearer.equals(that.isBasicBearer) : that.isBasicBearer != null)
return false;
if (bearerFormat != null ? !bearerFormat.equals(that.bearerFormat) : that.bearerFormat != null)
return false;
if (isOAuth != null ? !isOAuth.equals(that.isOAuth) : that.isOAuth != null)
return false;
if (isApiKey != null ? !isApiKey.equals(that.isApiKey) : that.isApiKey != null)
@@ -94,6 +101,9 @@ public class CodegenSecurity {
result = 31 * result + (type != null ? type.hashCode() : 0);
result = 31 * result + (hasMore != null ? hasMore.hashCode() : 0);
result = 31 * result + (isBasic != null ? isBasic.hashCode() : 0);
result = 31 * result + (isBasicBasic != null ? isBasicBasic.hashCode() : 0);
result = 31 * result + (isBasicBearer != null ? isBasicBearer.hashCode() : 0);
result = 31 * result + (bearerFormat != null ? bearerFormat.hashCode() : 0);
result = 31 * result + (isOAuth != null ? isOAuth.hashCode() : 0);
result = 31 * result + (isApiKey != null ? isApiKey.hashCode() : 0);
result = 31 * result + (vendorExtensions != null ? vendorExtensions.hashCode() : 0);

View File

@@ -3124,6 +3124,7 @@ public class DefaultCodegen implements CodegenConfig {
}
else if ("bearer".equals(securityScheme.getScheme())) {
cs.isBasicBearer = true;
cs.bearerFormat = securityScheme.getBearerFormat();
}
} else if (SecurityScheme.Type.OAUTH2.equals(securityScheme.getType())) {
cs.isKeyInHeader = cs.isKeyInQuery = cs.isKeyInCookie = cs.isApiKey = cs.isBasic = false;

View File

@@ -841,6 +841,10 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
bundle.put("hasOAuthMethods", true);
bundle.put("oauthMethods", getOAuthMethods(authMethods));
}
if (hasBearerMethods(authMethods)) {
bundle.put("hasBearerMethods", true);
}
}
List<CodegenServer> servers = config.fromServers(openAPI.getServers());
@@ -1194,6 +1198,16 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
return false;
}
private boolean hasBearerMethods(List<CodegenSecurity> authMethods) {
for (CodegenSecurity cs : authMethods) {
if (cs.isBasicBearer) {
return true;
}
}
return false;
}
private List<CodegenSecurity> getOAuthMethods(List<CodegenSecurity> authMethods) {
List<CodegenSecurity> oauthMethods = new ArrayList<>();

View File

@@ -60,4 +60,28 @@ public class ProcessUtils {
return false;
}
/**
* Returns true if at least one operation has Bearer security schema defined
*
* @param objs Map of operations
* @return True if at least one operation has Bearer security schema defined
*/
public static boolean hasBearerMethods(Map<String, Object> objs) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
if (operations != null) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
for (CodegenOperation operation : ops) {
if (operation.authMethods != null && !operation.authMethods.isEmpty()) {
for (CodegenSecurity cs : operation.authMethods) {
if (cs.isBasicBearer) {
return true;
}
}
}
}
}
return false;
}
}

View File

@@ -18,8 +18,23 @@ Method | HTTP request | Description
{{{notes}}}{{/notes}}
### Example
{{#hasAuthMethods}}{{#authMethods}}
{{#isBasic}}* Basic Authentication ({{name}}): {{/isBasic }}{{#isApiKey}}* Api Key Authentication ({{name}}): {{/isApiKey }}{{#isOAuth}}* OAuth Authentication ({{name}}): {{/isOAuth }}
{{#hasAuthMethods}}
{{#authMethods}}
{{#isBasic}}
{{^isBasicBearer}}
* Basic Authentication ({{name}}):
{{/isBasicBearer}}
{{#isBasicBearer}}
* Bearer{{#bearerFormat}} ({{{.}}}){{/bearerFormat}} Authentication ({{name}}):
{{/isBasicBearer}}
{{/isBasic}}
{{#isApiKey}}
* Api Key Authentication ({{name}}):
{{/isApiKey }}
{{#isOAuth}}
* OAuth Authentication ({{name}}):
{{/isOAuth }}
{{> api_doc_example }}
{{/authMethods}}
{{/hasAuthMethods}}

View File

@@ -4,25 +4,14 @@ import time
import {{{packageName}}}
from {{{packageName}}}.rest import ApiException
from pprint import pprint
{{> python_doc_auth_partial}}
{{#hasAuthMethods}}
configuration = {{{packageName}}}.Configuration(){{#isBasic}}
# Configure HTTP basic authorization: {{{name}}}
configuration.username = 'YOUR_USERNAME'
configuration.password = 'YOUR_PASSWORD'{{/isBasic}}{{#isApiKey}}
# Configure API key authorization: {{{name}}}
configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY'
# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed
# configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer'{{/isApiKey}}{{#isOAuth}}
# Configure OAuth2 access token for authorization: {{{name}}}
configuration.access_token = 'YOUR_ACCESS_TOKEN'{{/isOAuth}}
# create an instance of the API class
api_instance = {{{packageName}}}.{{{classname}}}({{{packageName}}}.ApiClient(configuration))
{{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}
{{/allParams}}
{{/hasAuthMethods}}
{{^hasAuthMethods}}
# create an instance of the API class
api_instance = {{{packageName}}}.{{{classname}}}()
{{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}

View File

@@ -4,19 +4,8 @@ import time
import {{{packageName}}}
from {{{packageName}}}.rest import ApiException
from pprint import pprint
{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}}{{#hasAuthMethods}}{{#authMethods}}
configuration = {{{packageName}}}.Configuration(){{#isBasic}}
# Configure HTTP basic authorization: {{{name}}}
configuration.username = 'YOUR_USERNAME'
configuration.password = 'YOUR_PASSWORD'{{/isBasic}}{{#isApiKey}}
# Configure API key authorization: {{{name}}}
configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY'
# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed
# configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer'{{/isApiKey}}{{#isOAuth}}
# Configure OAuth2 access token for authorization: {{{name}}}
configuration.access_token = 'YOUR_ACCESS_TOKEN'{{/isOAuth}}{{/authMethods}}
{{/hasAuthMethods}}
{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}}
{{> python_doc_auth_partial}}
# create an instance of the API class
api_instance = {{{packageName}}}.{{{classname}}}({{{packageName}}}.ApiClient(configuration))
{{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}
@@ -47,17 +36,28 @@ Class | Method | HTTP request | Description
## Documentation For Authorization
{{^authMethods}} All endpoints do not require authorization.
{{/authMethods}}{{#authMethods}}{{#last}} Authentication schemes defined for the API:{{/last}}{{/authMethods}}
{{#authMethods}}## {{{name}}}
{{^authMethods}}
All endpoints do not require authorization.
{{/authMethods}}
{{#authMethods}}
{{#last}} Authentication schemes defined for the API:{{/last}}
## {{{name}}}
{{#isApiKey}}- **Type**: API key
{{#isApiKey}}
- **Type**: API key
- **API key parameter name**: {{{keyParamName}}}
- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}}
{{/isApiKey}}
{{#isBasic}}- **Type**: HTTP basic authentication
{{#isBasic}}
{{^isBasicBearer}}
- **Type**: HTTP basic authentication
{{/isBasicBearer}}
{{#isBasicBearer}}
- **Type**: Bearer authentication{{#bearerFormat}} ({{{.}}}){{/bearerFormat}}
{{/isBasicBearer}}
{{/isBasic}}
{{#isOAuth}}- **Type**: OAuth
{{#isOAuth}}
- **Type**: OAuth
- **Flow**: {{{flow}}}
- **Authorization URL**: {{{authorizationUrl}}}
- **Scopes**: {{^scopes}}N/A{{/scopes}}

View File

@@ -51,10 +51,16 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)):
self.username = ""
# Password for HTTP basic authentication
self.password = ""
{{#authMethods}}{{#isOAuth}}
# access token for OAuth
{{#hasOAuthMethods}}
# access token for OAuth/Bearer
self.access_token = ""
{{/isOAuth}}{{/authMethods}}
{{/hasOAuthMethods}}
{{^hasOAuthMethods}}
{{#hasBearerMethods}}
# access token for OAuth/Bearer
self.access_token = ""
{{/hasBearerMethods}}
{{/hasOAuthMethods}}
# Logging Settings
self.logger = {}
self.logger["package_logger"] = logging.getLogger("{{packageName}}")
@@ -218,6 +224,7 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)):
},
{{/isApiKey}}
{{#isBasic}}
{{^isBasicBearer}}
'{{name}}':
{
'type': 'basic',
@@ -225,7 +232,21 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)):
'key': 'Authorization',
'value': self.get_basic_auth_token()
},
{{/isBasic}}{{#isOAuth}}
{{/isBasicBearer}}
{{#isBasicBearer}}
'{{name}}':
{
'type': 'bearer',
'in': 'header',
{{#bearerFormat}}
'format': '{{{.}}}',
{{/bearerFormat}}
'key': 'Authorization',
'value': 'Bearer ' + self.access_token
},
{{/isBasicBearer}}
{{/isBasic}}
{{#isOAuth}}
'{{name}}':
{
'type': 'oauth2',
@@ -233,7 +254,8 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)):
'key': 'Authorization',
'value': 'Bearer ' + self.access_token
},
{{/isOAuth}}{{/authMethods}}
{{/isOAuth}}
{{/authMethods}}
}
def to_debug_report(self):

View File

@@ -0,0 +1,26 @@
{{#hasAuthMethods}}
{{#authMethods}}
configuration = {{{packageName}}}.Configuration()
{{#isBasic}}
{{^isBasicBearer}}
# Configure HTTP basic authorization: {{{name}}}
configuration.username = 'YOUR_USERNAME'
configuration.password = 'YOUR_PASSWORD'
{{/isBasicBearer}}
{{#isBasicBearer}}
# Configure Bearer authorization{{#bearerFormat}} ({{{.}}}){{/bearerFormat}}: {{{name}}}
configuration.access_token = 'YOUR_BEARER_TOKEN'
{{/isBasicBearer}}
{{/isBasic}}
{{#isApiKey}}
# Configure API key authorization: {{{name}}}
configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY'
# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed
# configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer'
{{/isApiKey}}
{{#isOAuth}}
# Configure OAuth2 access token for authorization: {{{name}}}
configuration.access_token = 'YOUR_ACCESS_TOKEN'
{{/isOAuth}}
{{/authMethods}}
{{/hasAuthMethods}}

View File

@@ -768,6 +768,8 @@ paths:
delete:
tags:
- fake
security:
- bearer_test: []
summary: Fake endpoint to test group parameters (optional)
description: Fake endpoint to test group parameters (optional)
operationId: testGroupParameters
@@ -1096,6 +1098,10 @@ components:
http_basic_test:
type: http
scheme: basic
bearer_test:
type: http
scheme: bearer
bearerFormat: JWT
schemas:
Foo:
type: object