Skip to content

Commit

Permalink
refactor(cmd-api-server): pull OAuth2 endpoint scopes from openapi.json
Browse files Browse the repository at this point in the history
Primary Changes
----------------
1. added OAuth2 security endpoints scopes to openapi.json
2. added a test to make sure if the scopes are indeed getting
   pulled from the spec file

Fixes #2693

Signed-off-by: aldousalvarez <aldousss.alvarez@gmail.com>
  • Loading branch information
aldousalvarez committed Aug 7, 2024
1 parent 56dd9f8 commit 3321ed3
Show file tree
Hide file tree
Showing 13 changed files with 355 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Install the following dependencies:

```shell
go get github.com/stretchr/testify/assert
go get golang.org/x/oauth2
go get golang.org/x/net/context
```

Expand Down Expand Up @@ -91,7 +92,37 @@ Class | Method | HTTP request | Description

## Documentation For Authorization

Endpoints do not require authorization.

Authentication schemes defined for the API:
### OAuth2


- **Type**: OAuth
- **Flow**: accessCode
- **Authorization URL**: https://example.com/oauth/authorize
- **Scopes**:
- **read:health**: Read health information
- **read:metrics**: Read metrics information
- **read:spec**: Read OpenAPI specification

Example

```golang
auth := context.WithValue(context.Background(), sw.ContextAccessToken, "ACCESSTOKENSTRING")
r, err := client.Service.Operation(auth, args)
```

Or via OAuth2 module to automatically refresh tokens and perform user authentication.

```golang
import "golang.org/x/oauth2"

/* Perform OAuth2 round trip request and obtain a token */

tokenSource := oauth2cfg.TokenSource(createContext(httpClient), &token)
auth := context.WithValue(oauth2.NoContext, sw.ContextOAuth2, tokenSource)
r, err := client.Service.Operation(auth, args)
```


## Documentation for Utility Methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ info:
version: 2.0.0-rc.3
servers:
- url: /
security:
- OAuth2:
- read:health
- read:metrics
- read:spec
paths:
/api/v1/api-server/healthcheck:
get:
Expand All @@ -21,6 +26,9 @@ paths:
schema:
$ref: '#/components/schemas/HealthCheckResponse'
description: OK
security:
- OAuth2:
- read:health
summary: Can be used to verify liveness of an API server instance
x-hyperledger-cacti:
http:
Expand All @@ -37,6 +45,9 @@ paths:
schema:
$ref: '#/components/schemas/PrometheusExporterMetricsResponse'
description: OK
security:
- OAuth2:
- read:metrics
summary: Get the Prometheus Metrics
x-hyperledger-cacti:
http:
Expand All @@ -54,6 +65,9 @@ paths:
schema:
$ref: '#/components/schemas/GetOpenApiSpecV1EndpointResponse'
description: OK
security:
- OAuth2:
- read:spec
x-hyperledger-cacti:
http:
verbLowerCase: get
Expand Down Expand Up @@ -127,3 +141,14 @@ components:
GetOpenApiSpecV1EndpointResponse:
nullable: false
type: string
securitySchemes:
OAuth2:
flows:
authorizationCode:
authorizationUrl: https://example.com/oauth/authorize
scopes:
read:health: Read health information
read:metrics: Read metrics information
read:spec: Read OpenAPI specification
tokenUrl: https://example.com/oauth/token
type: oauth2

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ module github.com/hyperledger/cactus-cmd-api-server/src/main/go/generated/openap
go 1.18

require (
golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e h1:bRhVy7zSSasaqNksaRZiA5EEI+Ei4I1nO5Jh72wfHlg=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand Down
42 changes: 39 additions & 3 deletions packages/cactus-cmd-api-server/src/main/json/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,29 @@
"type": "string",
"nullable": false
}
},
"securitySchemes": {
"OAuth2": {
"type": "oauth2",
"flows": {
"authorizationCode": {
"authorizationUrl": "https://example.com/oauth/authorize",
"tokenUrl": "https://example.com/oauth/token",
"scopes": {
"read:health": "Read health information",
"read:metrics": "Read metrics information",
"read:spec": "Read OpenAPI specification"
}
}
}
}
}
},
"security": [
{
"OAuth2": ["read:health", "read:metrics", "read:spec"]
}
],
"paths": {
"/api/v1/api-server/healthcheck": {
"get": {
Expand All @@ -102,7 +123,12 @@
}
}
}
}
},
"security": [
{
"OAuth2": ["read:health"]
}
]
}
},
"/api/v1/api-server/get-prometheus-exporter-metrics": {
Expand All @@ -127,7 +153,12 @@
}
}
}
}
},
"security": [
{
"OAuth2": ["read:metrics"]
}
]
}
},
"/api/v1/api-server/get-open-api-spec": {
Expand All @@ -152,7 +183,12 @@
}
}
}
}
},
"security": [
{
"OAuth2": ["read:spec"]
}
]
}
}
}
Expand Down
42 changes: 39 additions & 3 deletions packages/cactus-cmd-api-server/src/main/json/openapi.tpl.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,29 @@
"type": "string",
"nullable": false
}
},
"securitySchemes": {
"OAuth2": {
"type": "oauth2",
"flows": {
"authorizationCode": {
"authorizationUrl": "https://example.com/oauth/authorize",
"tokenUrl": "https://example.com/oauth/token",
"scopes": {
"read:health": "Read health information",
"read:metrics": "Read metrics information",
"read:spec": "Read OpenAPI specification"
}
}
}
}
}
},
"security": [
{
"OAuth2": ["read:health", "read:metrics", "read:spec"]
}
],
"paths": {
"/api/v1/api-server/healthcheck": {
"get": {
Expand All @@ -102,7 +123,12 @@
}
}
}
}
},
"security": [
{
"OAuth2": ["read:health"]
}
]
}
},
"/api/v1/api-server/get-prometheus-exporter-metrics": {
Expand All @@ -127,7 +153,12 @@
}
}
}
}
},
"security": [
{
"OAuth2": ["read:metrics"]
}
]
}
},
"/api/v1/api-server/get-open-api-spec": {
Expand All @@ -152,7 +183,12 @@
}
}
}
}
},
"security": [
{
"OAuth2": ["read:spec"]
}
]
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,16 @@ Class | Method | HTTP request | Description
<a id="documentation-for-authorization"></a>
## Documentation for Authorization

Endpoints do not require authorization.

Authentication schemes defined for the API:
<a id="OAuth2"></a>
### OAuth2

- **Type**: OAuth
- **Flow**: accessCode
- **Authorization URL**: https://example.com/oauth/authorize
- **Scopes**:
- read:health: Read health information
- read:metrics: Read metrics information
- read:spec: Read OpenAPI specification

Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient
path = "/api/v1/api-server/healthcheck",
query = localVariableQuery,
headers = localVariableHeaders,
requiresAuthentication = false,
requiresAuthentication = true,
body = localVariableBody
)
}
Expand Down Expand Up @@ -176,7 +176,7 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient
path = "/api/v1/api-server/get-open-api-spec",
query = localVariableQuery,
headers = localVariableHeaders,
requiresAuthentication = false,
requiresAuthentication = true,
body = localVariableBody
)
}
Expand Down Expand Up @@ -243,7 +243,7 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient
path = "/api/v1/api-server/get-prometheus-exporter-metrics",
query = localVariableQuery,
headers = localVariableHeaders,
requiresAuthentication = false,
requiresAuthentication = true,
body = localVariableBody
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,20 @@ open class ApiClient(val baseUrl: String, val client: OkHttpClient = defaultClie
}
}

protected fun <T> updateAuthParams(requestConfig: RequestConfig<T>) {
if (requestConfig.headers[Authorization].isNullOrEmpty()) {
accessToken?.let { accessToken ->
requestConfig.headers[Authorization] = "Bearer $accessToken "
}
}
}

protected inline fun <reified I, reified T: Any?> request(requestConfig: RequestConfig<I>): ApiResponse<T?> {
val httpUrl = baseUrl.toHttpUrlOrNull() ?: throw IllegalStateException("baseUrl is invalid.")

// take authMethod from operation
updateAuthParams(requestConfig)

val url = httpUrl.newBuilder()
.addEncodedPathSegments(requestConfig.path.trimStart('/'))
.apply {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;

// authentication OAuth2 required
// oauth required
await setOAuthToObject(localVarHeaderParameter, "OAuth2", ["read:health"], configuration)



setSearchParams(localVarUrlObj, localVarQueryParameter);
Expand Down Expand Up @@ -157,6 +161,10 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;

// authentication OAuth2 required
// oauth required
await setOAuthToObject(localVarHeaderParameter, "OAuth2", ["read:spec"], configuration)



setSearchParams(localVarUrlObj, localVarQueryParameter);
Expand Down Expand Up @@ -187,6 +195,10 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;

// authentication OAuth2 required
// oauth required
await setOAuthToObject(localVarHeaderParameter, "OAuth2", ["read:metrics"], configuration)



setSearchParams(localVarUrlObj, localVarQueryParameter);
Expand Down
Loading

0 comments on commit 3321ed3

Please sign in to comment.