github.com/brycereitano/goa@v0.0.0-20170315073847-8ffa6c85e265/design/apidsl/security_test.go (about) 1 package apidsl_test 2 3 import ( 4 . "github.com/goadesign/goa/design" 5 . "github.com/goadesign/goa/design/apidsl" 6 "github.com/goadesign/goa/dslengine" 7 . "github.com/onsi/ginkgo" 8 . "github.com/onsi/gomega" 9 ) 10 11 var _ = Describe("Security", func() { 12 BeforeEach(func() { 13 dslengine.Reset() 14 }) 15 16 It("should have no security DSL when none are defined", func() { 17 API("secure", nil) 18 dslengine.Run() 19 Ω(Design.SecuritySchemes).Should(BeNil()) 20 Ω(dslengine.Errors).ShouldNot(HaveOccurred()) 21 }) 22 23 It("should be the fully valid and well defined, live on the happy path", func() { 24 API("secure", func() { 25 Host("example.com") 26 Scheme("http") 27 28 BasicAuthSecurity("basic_authz", func() { 29 Description("desc") 30 }) 31 32 OAuth2Security("googAuthz", func() { 33 Description("desc") 34 AccessCodeFlow("/auth", "/token") 35 Scope("user:read", "Read users") 36 }) 37 38 APIKeySecurity("a_key", func() { 39 Description("desc") 40 Query("access_token") 41 }) 42 43 JWTSecurity("jwt", func() { 44 Description("desc") 45 Header("Authorization") 46 TokenURL("/token") 47 Scope("user:read", "Read users") 48 Scope("user:write", "Write users") 49 }) 50 }) 51 52 dslengine.Run() 53 54 Ω(dslengine.Errors).ShouldNot(HaveOccurred()) 55 Ω(Design.SecuritySchemes).Should(HaveLen(4)) 56 57 Ω(Design.SecuritySchemes[0].Kind).Should(Equal(BasicAuthSecurityKind)) 58 Ω(Design.SecuritySchemes[0].Description).Should(Equal("desc")) 59 60 Ω(Design.SecuritySchemes[1].Kind).Should(Equal(OAuth2SecurityKind)) 61 Ω(Design.SecuritySchemes[1].AuthorizationURL).Should(Equal("http://example.com/auth")) 62 Ω(Design.SecuritySchemes[1].TokenURL).Should(Equal("http://example.com/token")) 63 Ω(Design.SecuritySchemes[1].Flow).Should(Equal("accessCode")) 64 65 Ω(Design.SecuritySchemes[2].Kind).Should(Equal(APIKeySecurityKind)) 66 Ω(Design.SecuritySchemes[2].In).Should(Equal("query")) 67 Ω(Design.SecuritySchemes[2].Name).Should(Equal("access_token")) 68 69 Ω(Design.SecuritySchemes[3].Kind).Should(Equal(JWTSecurityKind)) 70 Ω(Design.SecuritySchemes[3].TokenURL).Should(Equal("http://example.com/token")) 71 Ω(Design.SecuritySchemes[3].Scopes).Should(HaveLen(2)) 72 }) 73 74 Context("with basic security", func() { 75 It("should fail because of duplicate In declaration", func() { 76 API("", func() { 77 BasicAuthSecurity("broken_basic_authz", func() { 78 Description("desc") 79 Header("Authorization") 80 Query("access_token") 81 }) 82 }) 83 dslengine.Run() 84 Ω(dslengine.Errors).Should(HaveOccurred()) 85 }) 86 87 It("should fail because of invalid declaration of OAuth2Flow", func() { 88 API("", func() { 89 BasicAuthSecurity("broken_basic_authz", func() { 90 Description("desc") 91 ImplicitFlow("invalid") 92 }) 93 }) 94 dslengine.Run() 95 Ω(dslengine.Errors).Should(HaveOccurred()) 96 }) 97 98 It("should fail because of invalid declaration of TokenURL", func() { 99 API("", func() { 100 BasicAuthSecurity("broken_basic_authz", func() { 101 Description("desc") 102 TokenURL("/token") 103 }) 104 }) 105 dslengine.Run() 106 Ω(dslengine.Errors).Should(HaveOccurred()) 107 }) 108 109 It("should fail because of invalid declaration of TokenURL", func() { 110 API("", func() { 111 BasicAuthSecurity("broken_basic_authz", func() { 112 Description("desc") 113 TokenURL("in valid") 114 }) 115 }) 116 dslengine.Run() 117 Ω(dslengine.Errors).Should(HaveOccurred()) 118 }) 119 120 It("should fail because of invalid declaration of Header", func() { 121 API("", func() { 122 BasicAuthSecurity("broken_basic_authz", func() { 123 Description("desc") 124 Header("invalid") 125 }) 126 }) 127 dslengine.Run() 128 Ω(dslengine.Errors).Should(HaveOccurred()) 129 }) 130 }) 131 132 Context("with oauth2 security", func() { 133 It("should pass with valid values when well defined", func() { 134 API("", func() { 135 Host("example.com") 136 Scheme("http") 137 OAuth2Security("googAuthz", func() { 138 Description("Use Goog's Auth") 139 AccessCodeFlow("/auth", "/token") 140 Scope("scope:1", "Desc 1") 141 Scope("scope:2", "Desc 2") 142 }) 143 }) 144 Resource("one", func() { 145 Action("first", func() { 146 Routing(GET("/first")) 147 Security("googAuthz", func() { 148 Scope("scope:1") 149 }) 150 }) 151 }) 152 153 dslengine.Run() 154 155 Ω(dslengine.Errors).ShouldNot(HaveOccurred()) 156 Ω(Design.SecuritySchemes).Should(HaveLen(1)) 157 scheme := Design.SecuritySchemes[0] 158 Ω(scheme.Description).Should(Equal("Use Goog's Auth")) 159 Ω(scheme.AuthorizationURL).Should(Equal("http://example.com/auth")) 160 Ω(scheme.TokenURL).Should(Equal("http://example.com/token")) 161 Ω(scheme.Flow).Should(Equal("accessCode")) 162 Ω(scheme.Scopes["scope:1"]).Should(Equal("Desc 1")) 163 Ω(scheme.Scopes["scope:2"]).Should(Equal("Desc 2")) 164 }) 165 166 It("should fail because of invalid declaration of Header", func() { 167 API("", func() { 168 OAuth2Security("googAuthz", func() { 169 Header("invalid") 170 }) 171 }) 172 dslengine.Run() 173 Ω(dslengine.Errors).Should(HaveOccurred()) 174 }) 175 176 }) 177 178 Context("with resources and actions", func() { 179 It("should fallback properly to lower-level security", func() { 180 API("", func() { 181 JWTSecurity("jwt", func() { 182 TokenURL("/token") 183 Scope("read", "Read") 184 Scope("write", "Write") 185 }) 186 BasicAuthSecurity("password") 187 188 Security("jwt") 189 }) 190 Resource("one", func() { 191 Action("first", func() { 192 Routing(GET("/first")) 193 NoSecurity() 194 }) 195 Action("second", func() { 196 Routing(GET("/second")) 197 }) 198 }) 199 Resource("two", func() { 200 Security("password") 201 202 Action("third", func() { 203 Routing(GET("/third")) 204 }) 205 Action("fourth", func() { 206 Routing(GET("/fourth")) 207 Security("jwt") 208 }) 209 }) 210 Resource("three", func() { 211 Action("fifth", func() { 212 Routing(GET("/fifth")) 213 }) 214 }) 215 Resource("auth", func() { 216 NoSecurity() 217 218 Action("auth", func() { 219 Routing(GET("/auth")) 220 }) 221 Action("refresh", func() { 222 Routing(GET("/refresh")) 223 Security("jwt") 224 }) 225 }) 226 227 dslengine.Run() 228 229 Ω(dslengine.Errors).ShouldNot(HaveOccurred()) 230 Ω(Design.SecuritySchemes).Should(HaveLen(2)) 231 Ω(Design.Resources["one"].Actions["first"].Security).Should(BeNil()) 232 Ω(Design.Resources["one"].Actions["second"].Security.Scheme.SchemeName).Should(Equal("jwt")) 233 Ω(Design.Resources["two"].Actions["third"].Security.Scheme.SchemeName).Should(Equal("password")) 234 Ω(Design.Resources["two"].Actions["fourth"].Security.Scheme.SchemeName).Should(Equal("jwt")) 235 Ω(Design.Resources["three"].Actions["fifth"].Security.Scheme.SchemeName).Should(Equal("jwt")) 236 Ω(Design.Resources["auth"].Actions["auth"].Security).Should(BeNil()) 237 Ω(Design.Resources["auth"].Actions["refresh"].Security.Scheme.SchemeName).Should(Equal("jwt")) 238 }) 239 }) 240 })