@@ -81,6 +81,12 @@ def make_env(path = "/auth/ldap", props = {})
8181 expect ( last_response . body . scan ( "MyLdap Form" ) . size ) . to be > 1
8282 end
8383
84+ it "redirects to callback when POST includes username and password" do
85+ post "/auth/ldap" , { username : "alice" , password : "secret" } , { "REQUEST_METHOD" => "POST" }
86+ expect ( last_response ) . to be_redirect
87+ expect ( last_response . headers [ "Location" ] ) . to eq "http://example.org/auth/ldap/callback"
88+ end
89+
8490 context "when mounted under a subdirectory" do
8591 let ( :sub_env ) do
8692 make_env ( "/auth/ldap" , {
@@ -201,6 +207,41 @@ def make_env(path = "/auth/ldap", props = {})
201207 expect ( last_request . env [ "omniauth.error" ] . message ) . to eq ( "Invalid credentials for ping" )
202208 end
203209
210+ it "attaches password policy info to env when enabled" do
211+ allow ( @adaptor ) . to receive ( :password_policy ) . and_return ( true )
212+ ctrl = double ( "ppolicy" , error : :passwordExpired , time_before_expiration : 42 , grace_authns_remaining : 1 , oid : "1.3.6.1.4.1.42.2.27.8.5.1" )
213+ op = double ( "op" , code : 49 , message : "Invalid Credentials" )
214+ allow ( @adaptor ) . to receive ( :last_password_policy_response ) . and_return ( ctrl )
215+ allow ( @adaptor ) . to receive ( :last_operation_result ) . and_return ( op )
216+
217+ post ( "/auth/ldap/callback" , { username : "ping" , password : "password" } )
218+
219+ expect ( last_response ) . to be_redirect
220+ expect ( last_response . headers [ "Location" ] ) . to match ( "invalid_credentials" )
221+
222+ policy = last_request . env [ "omniauth.ldap.password_policy" ]
223+ expect ( policy ) . to be_a ( Hash )
224+ expect ( policy [ :error ] ) . to eq ( :passwordExpired )
225+ expect ( policy [ :time_before_expiration ] ) . to eq ( 42 )
226+ expect ( policy [ :grace_authns_remaining ] ) . to eq ( 1 )
227+ expect ( policy [ :oid ] ) . to eq ( "1.3.6.1.4.1.42.2.27.8.5.1" )
228+ expect ( policy [ :operation ] ) . to eq ( { code : 49 , message : "Invalid Credentials" } )
229+ end
230+
231+ it "maps alternate policy fields (ppolicy_error, grace_logins_remaining)" do
232+ allow ( @adaptor ) . to receive ( :password_policy ) . and_return ( true )
233+ ctrl = double ( "ppolicy" , ppolicy_error : :accountLocked , grace_logins_remaining : 0 , oid : "1.3.6.1.4.1.42.2.27.8.5.1" )
234+ allow ( @adaptor ) . to receive ( :last_password_policy_response ) . and_return ( ctrl )
235+ allow ( @adaptor ) . to receive ( :last_operation_result ) . and_return ( nil )
236+
237+ post ( "/auth/ldap/callback" , { username : "ping" , password : "password" } )
238+
239+ expect ( last_response ) . to be_redirect
240+ policy = last_request . env [ "omniauth.ldap.password_policy" ]
241+ expect ( policy [ :error ] ) . to eq ( :accountLocked )
242+ expect ( policy [ :grace_authns_remaining ] ) . to eq ( 0 )
243+ end
244+
204245 context "and filter is set" do
205246 it "binds with filter" do
206247 allow ( @adaptor ) . to receive ( :filter ) . and_return ( "uid=%{username}" )
@@ -275,6 +316,28 @@ def make_env(path = "/auth/ldap", props = {})
275316 expect ( last_response ) . not_to be_redirect
276317 end
277318
319+ it "attaches password policy env on success when enabled" do
320+ allow ( @adaptor ) . to receive ( :password_policy ) . and_return ( true )
321+ ctrl = double ( "ppolicy" , oid : "1.3.6.1.4.1.42.2.27.8.5.1" )
322+ allow ( @adaptor ) . to receive ( :last_password_policy_response ) . and_return ( ctrl )
323+ allow ( @adaptor ) . to receive ( :last_operation_result ) . and_return ( nil )
324+
325+ post ( "/auth/ldap/callback" , { username : "ping" , password : "password" } )
326+
327+ expect ( last_response ) . not_to be_redirect
328+ policy = last_request . env [ "omniauth.ldap.password_policy" ]
329+ expect ( policy ) . to be_a ( Hash )
330+ expect ( policy [ :oid ] ) . to eq ( "1.3.6.1.4.1.42.2.27.8.5.1" )
331+ expect ( policy [ :raw ] ) . to eq ( ctrl )
332+ end
333+
334+ it "uses equals filter when :filter is not configured" do
335+ allow ( @adaptor ) . to receive ( :filter ) . and_return ( nil )
336+ expect ( Net ::LDAP ::Filter ) . to receive ( :equals ) . with ( @adaptor . uid , "ping" ) . and_call_original
337+ post ( "/auth/ldap/callback" , { username : "ping" , password : "password" } )
338+ expect ( last_response ) . not_to be_redirect
339+ end
340+
278341 context "and filter is set" do
279342 it "binds with filter" do
280343 allow ( @adaptor ) . to receive ( :filter ) . and_return ( "uid=%{username}" )
0 commit comments