In Google Cloud Endpoints, I am unable to have authentication occur in an "or" scenario, where, for example, I want to allow access to a path by means of an api_key "or" oauth. Please see https://swagger.io/docs/specification/2-0/authentication/ for more info.
DOES WORK (single defintion for API key)
/api/query:
get:
operationId: queryget
responses:
'200':
description: query success
security:
- api_key: []
DOES WORK (single definition for oauth)
/api/query:
get:
operationId: queryget
responses:
'200':
description: query success
security:
- oauth: []
DOES WORK ("AND" definition where both must be included in auth)
/api/query:
get:
operationId: queryget
responses:
'200':
description: query success
security:
- oauth: []
api_key: []
DOES NOT WORK ("OR" definition)
/api/query:
get:
operationId: queryget
responses:
'200':
description: query success
security:
- oauth: []
- api_key: []
To be more specific when deploying my api to Google Cloud Endpoints, I receive the following warning
Operation 'get' in path '/api/query': Operation does not require an API key; callers may invoke the method without specifying an associated API-consuming project.
And, when trying to call the api with an API key, I receive the following error, as if it were expecting the OAUTH JWT token (maybe because it was the first security definition in the list for that route)
{ "code": 16, "message": "JWT validation failed: Missing or invalid credentials", "details": [ { "#type": "type.googleapis.com/google.rpc.DebugInfo", "stackEntries": [], "detail": "auth" } ]}'
This feature is unsupported, unfortunately. You can only use AND. This is now documented in Unsupported OpenAPI Features.
Related
Describing the problem
I was struggeling the last few days to figure out how to use apikey security in openapi, swagger, connexion for role based token authentication. The following OpenAPI 3.0 endpoint definition:
/lab/samples/list:
get:
tags:
- lab
summary: get a list of all registered samples
operationId: list_samples
responses:
"200":
description: successfully returned all available samples and their notification status
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Sample-For-Lab'
x-content-type: application/json
"400":
description: invalid request
content:
application/json:
schema:
$ref: '#/components/schemas/inline_response'
security:
- bearerAuth: ['labuser']
with the corresponding security definition
securitySchemes:
bearerAuth:
type: apiKey
name: Authorization
in: header
x-apikeyInfoFunc: swagger_server.controllers.authorization_controller.check_bearerAuth
So far so good. I built the corresponding server stubs using swagger-codegen, which follow the connexion security model and provide two fields api_key i.e. the bearer token and 'required_scopes' i.e. which should contain 'labuser'. When accessing the endpoint, the controller function is called:
def check_adminuserAuth(api_key, required_scopes):
return {'sample_key' : 'sample_value}
While the bearer token is properly passed, required_scopes is None. So there's no way of actually validating if credentials and permissions shown in the provided token actually match the endpoint's required scope of labuser in the authorization controller. I thought about handling validation in the called endpoints list_systemusers() but the token is no passed on by connexion.
Not supported in OpenAPI 3.0
After doing some digging, I found out that OpenAPI 3.0 provides apiKey validation on a global API level (i.e. authenticated or not), but does not offer support for individual scopes per endpoint. If you want individual scopes, you need to switch to OAuth security. However support for security scopes through apiKey security is coming in OpenAPI 3.1
Workaround
So for now the only way of making bearer token security with individual scopes work, is to actually define a security scheme for every scope e.g.
securitySchemes:
adminuserAuth:
type: apiKey
description: Provide your bearer token in the format **Bearer <token>**
name: Authorization
in: header
x-apikeyInfoFunc: swagger_server.controllers.authorization_controller.check_adminuserAuth
statsuserAuth:
type: apiKey
description: Provide your bearer token in the format **Bearer <token>**
name: Authorization
in: header
x-apikeyInfoFunc: swagger_server.controllers.authorization_controller.check_statsuserAuth
labuserAuth:
type: apiKey
description: Provide your bearer token in the format **Bearer <token>**
name: Authorization
in: header
x-apikeyInfoFunc: swagger_server.controllers.authorization_controller.check_labuserAuth
and on the path definition then add your required security authentication schemes
security:
- labuserAuth: []
- adminuserAuth: []
x-openapi-router-controller: swagger_server.controllers.lab_controller
Now I know by which authorization controller method is called the required scope a user needs to show and therefore can validate it against the ones shown in the token.
i am making openapi.yaml till now as well as deploying my test API's on the google cloud endpoints is working but now i made some changes i am sending parameter in body to the get api (e.g email) and getting some response but actually on the local it is working fine with postman after deploying openapi.yaml file it is not working on the google cloud endponits portal
So, anybody has any solution or answers for this so please help me
For safety i am also sharing error screenshot also y code snippet
"/api/getRecords":
get:
description: "Get All Records Details."
operationId: "getRecords"
produces:
- "application/json"
parameters:
- description: "Message to getRecords"
in: query
name: getRecords
type: object
required: false
schema:
$ref: "#/definitions/echoMessage"
responses:
200:
Also,
Try your code like this :
# [START swagger]
swagger: "2.0"
info:
description: "A simple Google Cloud Endpoints API example."
title: "Endpoints Example"
version: "1.0.0"
host: "abc.appspot.com"
# [END swagger]
parameters:
email:
name: email
in: query
type: string
required: true
Then use shorthand syntax in the path:
path:
"/api/getRecords":
get:
description: "Get All Records Details."
operationId: "getRecords"
parameters:
- $ref: "#/parameters/email"
responses:
200:
description: "Get records details"
schema:
$ref: "#/definitions/postMessage"
It will work.
I'm writing the swagger under OAS 3.0.2 specification. And wondering if it is possible to set the authorization value (BearerAuth) through the operation return value.
Now I need to call the api/login first and then copy return token and paste to authorize panel. Is there have better way to auto link the value between operation and security?
I've tried to use Links, but I am not sure that support on security. (The official document do not mention the way to implement on security)
paths:
/login:
post:
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
account:
type: string
password:
type: string
responses:
'200':
description: data.apiToken
content:
application/json:
schema:
type: object
properties:
data:
type: object
description: data
properties:
apiToken:
type: string
description: I need this as authorization value
links:
ApiToken:
operationId: apiToken
parameters:
apiToken: '$response.body#/data.apiToken'
The login was success, and response body like:
{
"data":{
"apiToken": "xxxxxx"
}
}
But next step I have no idea how to do. The response is 401 because token not being sent in headers (...I'm not surprise).
/someapi:
get:
summary: This API need auth to get data
operationId: apiToken
security:
- BearerAuth: [apiToken]
responses:
'401':
description: Not work
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
If I copy/paste manually, it could be authorized successfully. Is there any way to solve this issue or just not support this feature right now? Thank you so much.
I'm trying to run the following code:
/v1/test/{id}:
x-swagger-router-controller: Security
get:
operationId: test
description: "Test jwt middleware and multiple paths"
security:
- JWT: []
parameters:
- name: "id"
in: "path"
description: "ID of user"
required: true
type: "integer"
responses:
"200":
description: "Success"
schema:
$ref: "#/definitions/LoginSuccess"
"403":
description: "Access Denied"
schema:
$ref: "#/definitions/Error"
/v2/test/{id}:
$ref: "#/paths/~1v1~1test~1{id}"
But i'm receiving the following error:
API Errors:
#/paths/~1v2~1test~1{id}/$ref: Path could not be resolved:
/paths/~1v1~1test~1{id}
How can i fix this?
In this particular case what I really needed to achieve was to be able to version my API especially where not all methods had a newer version yet ie where for example /api/v1/method and /api/v2/method were still destined for the same function.
I thus solved it as follows
parameters:
- name: version
in: path
description: Version number of API
required: true
type: string
enum: &APIVERSION
- v1
- v2
In this way both v1 and v2 went to the same place. I can also add v3 etc to the enum which is reusable by different paths as enum: *APIVERSION
I have the following spec.yaml file
swagger: '2.0'
info:
title: Store API
version: "0.3.5"
host: SELF_URL_REPLACED_BY_APP
schemes:
- https
basePath: /
produces:
- application/json
tags:
- name: account
- name: transcripts
security:
- auth0:
- openid
- apiKey: []
securityDefinitions:
auth0:
type: oauth2
authorizationUrl: https://store.auth0.com/authorize
flow: implicit
tokenName: id_token
scopes:
openid: Grant access to user
apiKey:
type: apiKey
name: Authorization
in: header
I get this error when i try to validate it in http://editor.swagger.io/:
✖ Swagger Error
Not a valid securityDefinitions definition
Jump to line 19
Details
Object
code: "ONE_OF_MISSING"
params: Array [0]
message: "Not a valid securityDefinitions definition"
path: Array [2]
schemaId: "http://swagger.io/v2/schema.json#"
inner: Array [6]
level: 900
type: "Swagger Error"
description: "Not a valid securityDefinitions definition"
lineNumber: 19
What am I missing? I am able to login using Auth0 and everything seems to work fine.
Any advice is much appreciated.
tokenName is not a valid property of the SecurityDefinitions object.
However your Swagger definition has other errors - such as no paths - which may cause it to give incorrect validation errors about securityDefinitions as you're editing.
The following for instance should validate fine:
swagger: '2.0'
info:
title: Store API
version: "0.3.5"
host: SELF_URL_REPLACED_BY_APP
schemes:
- https
basePath: /
produces:
- application/json
tags:
- name: account
- name: transcripts
paths:
/pets:
get:
description: Returns all pets from the system that the user has access to
produces:
- application/json
responses:
'200':
description: A list of pets.
schema:
type: array
items:
type: string
security:
- auth0:
- openid
- apiKey: []
securityDefinitions:
auth0:
type: oauth2
authorizationUrl: https://store.auth0.com/authorize
flow: implicit
scopes:
openid: Grant access to user
apiKey:
type: apiKey
name: Authorization
in: header
Also the security section does not belong at the top level, but should be placed under each API method (see above definition for an example) to specify which security definitions should be applied to that API.