Repository: goadesign/goa
Pull request #3399 (2023-10-19 21:21:21)

bugfix: export proper scopes in openapi3 file for oauth2 and jwt security
In openapi yaml file listed all scopes available for authentication method. Instead there should be only scopes mentioned for specific endpoint.

Note: Swagger file isn't affected by this bug.

raphael: Good catch! thank you.
raphael: Can you address the [lint issue](https://app.deepsource.com/gh/goadesign/goa/run/b480e3cf-6a34-41f4-96a9-92a10a809e94/go/SCC-S1001?listindex=0)? thank you!

Patch:
diff --git a/http/codegen/openapi/v3/builder.go b/http/codegen/openapi/v3/builder.go
index 5859d55c..55034927 100644
--- a/http/codegen/openapi/v3/builder.go
+++ b/http/codegen/openapi/v3/builder.go
@@ -549,11 +549,7 @@ func buildSecurityRequirements(reqs []*expr.SecurityExpr) []map[string][]string
 			case expr.BasicAuthKind, expr.APIKeyKind:
 				sr[sch.Hash()] = []string{}
 			case expr.OAuth2Kind, expr.JWTKind:
-				scopes := make([]string, len(sch.Scopes))
-				for i, scope := range sch.Scopes {
-					scopes[i] = scope.Name
-				}
-				sr[sch.Hash()] = scopes
+				sr[sch.Hash()] = req.Scopes
 			}
 		}
 		srs[i] = sr


Test patch:
diff --git a/http/codegen/openapi/v3/testdata/golden/security_file0.golden b/http/codegen/openapi/v3/testdata/golden/security_file0.golden
index 4ca40dd6..63871908 100644
--- a/http/codegen/openapi/v3/testdata/golden/security_file0.golden
+++ b/http/codegen/openapi/v3/testdata/golden/security_file0.golden
@@ -1,1 +1,1 @@
-{"openapi":"3.0.3","info":{"title":"Goa API","version":"1.0"},"servers":[{"url":"http://localhost:80","description":"Default server for test api"}],"paths":{"/":{"get":{"tags":["testService"],"summary":"testEndpointA testService","operationId":"testService#testEndpointA","parameters":[{"name":"k","in":"query","allowEmptyValue":true,"required":true,"schema":{"type":"string","example":"Quia molestias."},"example":"Doloribus qui quia."},{"name":"Token","in":"header","allowEmptyValue":true,"required":true,"schema":{"type":"string","example":"Et tempora et quae."},"example":"Itaque inventore optio."},{"name":"X-Authorization","in":"header","allowEmptyValue":true,"required":true,"schema":{"type":"string","example":"Ullam aut."},"example":"Iste perspiciatis."}],"responses":{"204":{"description":"No Content response."}},"security":[{"api_key_query_k":[],"basic_header_Authorization":[],"jwt_header_X-Authorization":["api:read","api:write"],"oauth2_header_Token":["api:read","api:write"]}]},"post":{"tags":["testService"],"summary":"testEndpointB testService","operationId":"testService#testEndpointB","parameters":[{"name":"auth","in":"query","allowEmptyValue":true,"required":true,"schema":{"type":"string","example":"Harum et."},"example":"Neque nisi quibusdam nisi sint sunt."}],"responses":{"204":{"description":"No Content response."}},"security":[{"api_key_header_Authorization":[]},{"oauth2_query_auth":["api:read","api:write"]}]}}},"components":{"securitySchemes":{"api_key_header_Authorization":{"type":"apiKey","description":"Secures endpoint by requiring an API key.","name":"Authorization","in":"header"},"api_key_query_k":{"type":"apiKey","description":"Secures endpoint by requiring an API key.","name":"k","in":"query"},"basic_header_Authorization":{"type":"http","description":"Basic authentication used to authenticate security principal during signin","scheme":"basic"},"jwt_header_X-Authorization":{"type":"http","description":"Secures endpoint by requiring a valid JWT token retrieved via the signin endpoint. Supports scopes \"api:read\" and \"api:write\".","scheme":"bearer"},"oauth2_header_Token":{"type":"oauth2","description":"Secures endpoint by requiring a valid OAuth2 token retrieved via the signin endpoint. Supports scopes \"api:read\" and \"api:write\".","flows":{"authorizationCode":{"authorizationUrl":"http://goa.design/authorization","tokenUrl":"http://goa.design/token","refreshUrl":"http://goa.design/refresh","scopes":{"api:read":"Read-only access","api:write":"Read and write access"}}}},"oauth2_query_auth":{"type":"oauth2","description":"Secures endpoint by requiring a valid OAuth2 token retrieved via the signin endpoint. Supports scopes \"api:read\" and \"api:write\".","flows":{"authorizationCode":{"authorizationUrl":"http://goa.design/authorization","tokenUrl":"http://goa.design/token","refreshUrl":"http://goa.design/refresh","scopes":{"api:read":"Read-only access","api:write":"Read and write access"}}}}}},"tags":[{"name":"testService"}]}
\ No newline at end of file
+{"openapi":"3.0.3","info":{"title":"Goa API","version":"1.0"},"servers":[{"url":"http://localhost:80","description":"Default server for test api"}],"paths":{"/":{"get":{"tags":["testService"],"summary":"testEndpointA testService","operationId":"testService#testEndpointA","parameters":[{"name":"k","in":"query","allowEmptyValue":true,"required":true,"schema":{"type":"string","example":"Quia molestias."},"example":"Doloribus qui quia."},{"name":"Token","in":"header","allowEmptyValue":true,"required":true,"schema":{"type":"string","example":"Et tempora et quae."},"example":"Itaque inventore optio."},{"name":"X-Authorization","in":"header","allowEmptyValue":true,"required":true,"schema":{"type":"string","example":"Ullam aut."},"example":"Iste perspiciatis."}],"responses":{"204":{"description":"No Content response."}},"security":[{"api_key_query_k":[],"basic_header_Authorization":[],"jwt_header_X-Authorization":["api:read"],"oauth2_header_Token":["api:read"]}]},"post":{"tags":["testService"],"summary":"testEndpointB testService","operationId":"testService#testEndpointB","parameters":[{"name":"auth","in":"query","allowEmptyValue":true,"required":true,"schema":{"type":"string","example":"Harum et."},"example":"Neque nisi quibusdam nisi sint sunt."}],"responses":{"204":{"description":"No Content response."}},"security":[{"api_key_header_Authorization":[]},{"oauth2_query_auth":["api:read","api:write"]}]}}},"components":{"securitySchemes":{"api_key_header_Authorization":{"type":"apiKey","description":"Secures endpoint by requiring an API key.","name":"Authorization","in":"header"},"api_key_query_k":{"type":"apiKey","description":"Secures endpoint by requiring an API key.","name":"k","in":"query"},"basic_header_Authorization":{"type":"http","description":"Basic authentication used to authenticate security principal during signin","scheme":"basic"},"jwt_header_X-Authorization":{"type":"http","description":"Secures endpoint by requiring a valid JWT token retrieved via the signin endpoint. Supports scopes \"api:read\" and \"api:write\".","scheme":"bearer"},"oauth2_header_Token":{"type":"oauth2","description":"Secures endpoint by requiring a valid OAuth2 token retrieved via the signin endpoint. Supports scopes \"api:read\" and \"api:write\".","flows":{"authorizationCode":{"authorizationUrl":"http://goa.design/authorization","tokenUrl":"http://goa.design/token","refreshUrl":"http://goa.design/refresh","scopes":{"api:read":"Read-only access","api:write":"Read and write access"}}}},"oauth2_query_auth":{"type":"oauth2","description":"Secures endpoint by requiring a valid OAuth2 token retrieved via the signin endpoint. Supports scopes \"api:read\" and \"api:write\".","flows":{"authorizationCode":{"authorizationUrl":"http://goa.design/authorization","tokenUrl":"http://goa.design/token","refreshUrl":"http://goa.design/refresh","scopes":{"api:read":"Read-only access","api:write":"Read and write access"}}}}}},"tags":[{"name":"testService"}]}
\ No newline at end of file
diff --git a/http/codegen/openapi/v3/testdata/golden/security_file1.golden b/http/codegen/openapi/v3/testdata/golden/security_file1.golden
index 55d73c2a..f83c0719 100644
--- a/http/codegen/openapi/v3/testdata/golden/security_file1.golden
+++ b/http/codegen/openapi/v3/testdata/golden/security_file1.golden
@@ -45,10 +45,8 @@ paths:
                   basic_header_Authorization: []
                   jwt_header_X-Authorization:
                     - api:read
-                    - api:write
                   oauth2_header_Token:
                     - api:read
-                    - api:write
         post:
             tags:
                 - testService