Repository: danielgtaylor/huma
Pull request #55 (2022-07-04 17:21:25)

fix: add all `security scheme object` in OpenAPI 3.0.3
see: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#security-scheme-object

Thanks for your work! 😄 


Patch:
diff --git a/openapi.go b/openapi.go
index a0c1662..e63a602 100644
--- a/openapi.go
+++ b/openapi.go
@@ -157,8 +157,32 @@ type oaFlows struct {
 	AuthorizationCode *oaFlow `json:"authorizationCode,omitempty"`
 }
 
+type SecurityScheme string
+
+const (
+	SecuritySchemeApiKey        SecurityScheme = "apiKey"
+	SecuritySchemeHTTP          SecurityScheme = "http"
+	SecuritySchemeOauth2        SecurityScheme = "oauth2"
+	SecuritySchemeOpenIdConnect SecurityScheme = "openIdConnect"
+)
+
+// paramLocation describes where in the HTTP request the parameter comes from.
+type APIKeyLocation string
+
+// Parameter locations supported by OpenAPI 3
+const (
+	keyInQuery  APIKeyLocation = "query"
+	keyInHeader APIKeyLocation = "header"
+	keyInCookie APIKeyLocation = "cookie"
+)
+
 type oaSecurityScheme struct {
-	Type   string  `json:"type"`
-	Scheme string  `json:"scheme,omitempty"`
-	Flows  oaFlows `json:"flows,omitempty"`
+	Type             SecurityScheme `json:"type"`
+	Description      string         `json:"description,omitempty"`
+	Name             string         `json:"name,omitempty"`
+	In               APIKeyLocation `json:"in,omitempty"`
+	Scheme           string         `json:"scheme,omitempty"`
+	BearerFormat     string         `json:"bearerFormat,omitempty"`
+	Flows            *oaFlows       `json:"flows,omitempty"`
+	OpenIdConnectUrl string         `json:"openIdConnectUrl,omitempty"`
 }
diff --git a/router.go b/router.go
index 59401b3..9ee7617 100644
--- a/router.go
+++ b/router.go
@@ -139,17 +139,46 @@ func (r *Router) ServerLink(description, uri string) {
 // GatewayBasicAuth documents that the API gateway handles auth using HTTP Basic.
 func (r *Router) GatewayBasicAuth(name string) {
 	r.securitySchemes[name] = oaSecurityScheme{
-		Type:   "http",
+		Type:   SecuritySchemeHTTP,
 		Scheme: "basic",
 	}
 }
 
+// GatewayBearerFormat documents that the API gateway handles auth using HTTP Bearer.
+func (r *Router) GatewayBearerFormat(name string, description string, format string) {
+	r.securitySchemes[name] = oaSecurityScheme{
+		Type:         SecuritySchemeHTTP,
+		Description:  description,
+		Scheme:       "bearer",
+		BearerFormat: format,
+	}
+}
+
+// GatewayAPIKey documents that the API gateway handles auth using API Key.
+func (r *Router) GatewayAPIKey(name string, description string, keyName string, in APIKeyLocation) {
+	r.securitySchemes[name] = oaSecurityScheme{
+		Type:        SecuritySchemeApiKey,
+		Description: description,
+		Name:        keyName,
+		In:          in,
+	}
+}
+
+// GatewayOpenIDConnect documents that the API gateway handles auth using openIdConnect.
+func (r *Router) GatewayOpenIDConnect(name string, description string, url string) {
+	r.securitySchemes[name] = oaSecurityScheme{
+		Type:             SecuritySchemeOpenIdConnect,
+		Description:      description,
+		OpenIdConnectUrl: url,
+	}
+}
+
 // GatewayClientCredentials documents that the API gateway handles auth using
 // OAuth2 client credentials (pre-shared secret).
 func (r *Router) GatewayClientCredentials(name, tokenURL string, scopes map[string]string) {
 	r.securitySchemes[name] = oaSecurityScheme{
 		Type: "oauth2",
-		Flows: oaFlows{
+		Flows: &oaFlows{
 			ClientCredentials: &oaFlow{
 				TokenURL: tokenURL,
 				Scopes:   scopes,
@@ -163,7 +192,7 @@ func (r *Router) GatewayClientCredentials(name, tokenURL string, scopes map[stri
 func (r *Router) GatewayAuthCode(name, authorizeURL, tokenURL string, scopes map[string]string) {
 	r.securitySchemes[name] = oaSecurityScheme{
 		Type: "oauth2",
-		Flows: oaFlows{
+		Flows: &oaFlows{
 			AuthorizationCode: &oaFlow{
 				AuthorizationURL: authorizeURL,
 				TokenURL:         tokenURL,


Test patch:
diff --git a/router_test.go b/router_test.go
index 626210b..2d76b38 100644
--- a/router_test.go
+++ b/router_test.go
@@ -304,6 +304,9 @@ func TestRouterSecurity(t *testing.T) {
 	app.GatewayAuthCode("default", "https://example.com/authorize", "https://example.com/token", nil)
 	app.GatewayClientCredentials("m2m", "https://example.com/token", nil)
 	app.GatewayBasicAuth("basic")
+	app.GatewayBearerFormat("bearer", "JWT bearer description", "JWT")
+	app.GatewayAPIKey("apikey", "api key", "key", keyInHeader)
+	app.GatewayOpenIDConnect("openid", "Open ID", "https://example.com/OpenID")
 
 	// Every call must be authenticated using the default auth mechanism
 	// registered above.
@@ -345,7 +348,23 @@ func TestRouterSecurity(t *testing.T) {
 		"basic": map[string]interface{}{
 			"type":   "http",
 			"scheme": "basic",
-			"flows":  map[string]interface{}{},
+		},
+		"bearer": map[string]interface{}{
+			"type":         "http",
+			"scheme":       "bearer",
+			"description":  "JWT bearer description",
+			"bearerFormat": "JWT",
+		},
+		"apikey": map[string]interface{}{
+			"type":        "apiKey",
+			"name":        "key",
+			"in":          "header",
+			"description": "api key",
+		},
+		"openid": map[string]interface{}{
+			"type":             "openIdConnect",
+			"description":      "Open ID",
+			"openIdConnectUrl": "https://example.com/OpenID",
 		},
 	})
 }